* libc/stdio/fclose.c: Only use sfp lock to guard non-atomic
changes of flags and fp lock. * libc/stdio/freopen.c: Ditto. * libc/stdio/freopen64.c: Ditto. * libc/stdio/fgetc.c: Revert change from 2009-04-24, remove sfp locks which guard entire function to avoid potential deadlocks when using stdio functions in multiple thraeds. * libc/stdio/fgets.c: Ditto. * libc/stdio/fgetwc.c: Ditto. * libc/stdio/fgetws.c: Ditto. * libc/stdio/fread.c: Ditto. * libc/stdio/fseek.c: Ditto. * libc/stdio/getc.c: Ditto. * libc/stdio/getdelim.c: Ditto. * libc/stdio/gets.c: Ditto. * libc/stdio/vfscanf.c: Ditto. * libc/stdio/vfwscanf.c: Ditto. * libc/stdio/fflush.c (_fflush_r): Split out core functionality into new function __sflush_r. Just lock file and call __sflush_r from here. * libc/stdio/fwalk.c (_fwalk): Remove static helper function and move functionality back into main function. Don't walk a file with flags value of 1. Add comment. (_fwalk_reent): Ditto. * libc/stdio/local.h (__sflush_r): Declare. * libc/stdio/refill.c (__srefill): Before calling fwalk, set flags value to 1 so this file pointer isn't walked. Revert flags afterwards and call __sflush_r for this fp if necessary. Add comments.
This commit is contained in:
parent
b5ca0d7271
commit
656df313e0
|
@ -1,3 +1,34 @@
|
||||||
|
2011-01-28 Corinna Vinschen <vinschen@redhat.com>
|
||||||
|
|
||||||
|
* libc/stdio/fclose.c: Only use sfp lock to guard non-atomic
|
||||||
|
changes of flags and fp lock.
|
||||||
|
* libc/stdio/freopen.c: Ditto.
|
||||||
|
* libc/stdio/freopen64.c: Ditto.
|
||||||
|
* libc/stdio/fgetc.c: Revert change from 2009-04-24, remove sfp locks
|
||||||
|
which guard entire function to avoid potential deadlocks when using
|
||||||
|
stdio functions in multiple thraeds.
|
||||||
|
* libc/stdio/fgets.c: Ditto.
|
||||||
|
* libc/stdio/fgetwc.c: Ditto.
|
||||||
|
* libc/stdio/fgetws.c: Ditto.
|
||||||
|
* libc/stdio/fread.c: Ditto.
|
||||||
|
* libc/stdio/fseek.c: Ditto.
|
||||||
|
* libc/stdio/getc.c: Ditto.
|
||||||
|
* libc/stdio/getdelim.c: Ditto.
|
||||||
|
* libc/stdio/gets.c: Ditto.
|
||||||
|
* libc/stdio/vfscanf.c: Ditto.
|
||||||
|
* libc/stdio/vfwscanf.c: Ditto.
|
||||||
|
|
||||||
|
* libc/stdio/fflush.c (_fflush_r): Split out core functionality into
|
||||||
|
new function __sflush_r. Just lock file and call __sflush_r from here.
|
||||||
|
* libc/stdio/fwalk.c (_fwalk): Remove static helper function and move
|
||||||
|
functionality back into main function. Don't walk a file with flags
|
||||||
|
value of 1. Add comment.
|
||||||
|
(_fwalk_reent): Ditto.
|
||||||
|
* libc/stdio/local.h (__sflush_r): Declare.
|
||||||
|
* libc/stdio/refill.c (__srefill): Before calling fwalk, set flags
|
||||||
|
value to 1 so this file pointer isn't walked. Revert flags afterwards
|
||||||
|
and call __sflush_r for this fp if necessary. Add comments.
|
||||||
|
|
||||||
2011-01-27 Corinna Vinschen <vinschen@redhat.com>
|
2011-01-27 Corinna Vinschen <vinschen@redhat.com>
|
||||||
|
|
||||||
* libc/include/sys/features.h: Define __STDC_ISO_10646__ for Cygwin.
|
* libc/include/sys/features.h: Define __STDC_ISO_10646__ for Cygwin.
|
||||||
|
|
|
@ -74,8 +74,6 @@ _DEFUN(_fclose_r, (rptr, fp),
|
||||||
if (fp == NULL)
|
if (fp == NULL)
|
||||||
return (0); /* on NULL */
|
return (0); /* on NULL */
|
||||||
|
|
||||||
__sfp_lock_acquire ();
|
|
||||||
|
|
||||||
CHECK_INIT (rptr, fp);
|
CHECK_INIT (rptr, fp);
|
||||||
|
|
||||||
_flockfile (fp);
|
_flockfile (fp);
|
||||||
|
@ -83,7 +81,6 @@ _DEFUN(_fclose_r, (rptr, fp),
|
||||||
if (fp->_flags == 0) /* not open! */
|
if (fp->_flags == 0) /* not open! */
|
||||||
{
|
{
|
||||||
_funlockfile (fp);
|
_funlockfile (fp);
|
||||||
__sfp_lock_release ();
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
/* Unconditionally flush to allow special handling for seekable read
|
/* Unconditionally flush to allow special handling for seekable read
|
||||||
|
@ -98,6 +95,7 @@ _DEFUN(_fclose_r, (rptr, fp),
|
||||||
FREEUB (rptr, fp);
|
FREEUB (rptr, fp);
|
||||||
if (HASLB (fp))
|
if (HASLB (fp))
|
||||||
FREELB (rptr, fp);
|
FREELB (rptr, fp);
|
||||||
|
__sfp_lock_acquire ();
|
||||||
fp->_flags = 0; /* release this FILE for reuse */
|
fp->_flags = 0; /* release this FILE for reuse */
|
||||||
_funlockfile (fp);
|
_funlockfile (fp);
|
||||||
#ifndef __SINGLE_THREAD__
|
#ifndef __SINGLE_THREAD__
|
||||||
|
|
|
@ -67,37 +67,16 @@ No supporting OS subroutines are required.
|
||||||
|
|
||||||
/* Flush a single file, or (if fp is NULL) all files. */
|
/* Flush a single file, or (if fp is NULL) all files. */
|
||||||
|
|
||||||
|
/* Core function which does not lock file pointer. This gets called
|
||||||
|
directly from __srefill. */
|
||||||
int
|
int
|
||||||
_DEFUN(_fflush_r, (ptr, fp),
|
_DEFUN(__sflush_r, (ptr, fp),
|
||||||
struct _reent *ptr _AND
|
struct _reent *ptr _AND
|
||||||
register FILE * fp)
|
register FILE * fp)
|
||||||
{
|
{
|
||||||
register unsigned char *p;
|
register unsigned char *p;
|
||||||
register int n, t;
|
register int n, t;
|
||||||
|
|
||||||
#ifdef _REENT_SMALL
|
|
||||||
/* For REENT_SMALL platforms, it is possible we are being
|
|
||||||
called for the first time on a std stream. This std
|
|
||||||
stream can belong to a reentrant struct that is not
|
|
||||||
_REENT. If CHECK_INIT gets called below based on _REENT,
|
|
||||||
we will end up changing said file pointers to the equivalent
|
|
||||||
std stream off of _REENT. This causes unexpected behavior if
|
|
||||||
there is any data to flush on the _REENT std stream. There
|
|
||||||
are two alternatives to fix this: 1) make a reentrant fflush
|
|
||||||
or 2) simply recognize that this file has nothing to flush
|
|
||||||
and return immediately before performing a CHECK_INIT. Choice
|
|
||||||
2 is implemented here due to its simplicity. */
|
|
||||||
if (fp->_bf._base == NULL)
|
|
||||||
return 0;
|
|
||||||
#endif /* _REENT_SMALL */
|
|
||||||
|
|
||||||
CHECK_INIT (ptr, fp);
|
|
||||||
|
|
||||||
if (!fp->_flags)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
_flockfile (fp);
|
|
||||||
|
|
||||||
t = fp->_flags;
|
t = fp->_flags;
|
||||||
if ((t & __SWR) == 0)
|
if ((t & __SWR) == 0)
|
||||||
{
|
{
|
||||||
|
@ -150,7 +129,6 @@ _DEFUN(_fflush_r, (ptr, fp),
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
fp->_flags |= __SERR;
|
fp->_flags |= __SERR;
|
||||||
_funlockfile (fp);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -186,17 +164,14 @@ _DEFUN(_fflush_r, (ptr, fp),
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fp->_flags |= __SERR;
|
fp->_flags |= __SERR;
|
||||||
_funlockfile (fp);
|
|
||||||
return EOF;
|
return EOF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_funlockfile (fp);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if ((p = fp->_bf._base) == NULL)
|
if ((p = fp->_bf._base) == NULL)
|
||||||
{
|
{
|
||||||
/* Nothing to flush. */
|
/* Nothing to flush. */
|
||||||
_funlockfile (fp);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
n = fp->_p - p; /* write this much */
|
n = fp->_p - p; /* write this much */
|
||||||
|
@ -215,16 +190,48 @@ _DEFUN(_fflush_r, (ptr, fp),
|
||||||
if (t <= 0)
|
if (t <= 0)
|
||||||
{
|
{
|
||||||
fp->_flags |= __SERR;
|
fp->_flags |= __SERR;
|
||||||
_funlockfile (fp);
|
|
||||||
return EOF;
|
return EOF;
|
||||||
}
|
}
|
||||||
p += t;
|
p += t;
|
||||||
n -= t;
|
n -= t;
|
||||||
}
|
}
|
||||||
_funlockfile (fp);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_DEFUN(_fflush_r, (ptr, fp),
|
||||||
|
struct _reent *ptr _AND
|
||||||
|
register FILE * fp)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
#ifdef _REENT_SMALL
|
||||||
|
/* For REENT_SMALL platforms, it is possible we are being
|
||||||
|
called for the first time on a std stream. This std
|
||||||
|
stream can belong to a reentrant struct that is not
|
||||||
|
_REENT. If CHECK_INIT gets called below based on _REENT,
|
||||||
|
we will end up changing said file pointers to the equivalent
|
||||||
|
std stream off of _REENT. This causes unexpected behavior if
|
||||||
|
there is any data to flush on the _REENT std stream. There
|
||||||
|
are two alternatives to fix this: 1) make a reentrant fflush
|
||||||
|
or 2) simply recognize that this file has nothing to flush
|
||||||
|
and return immediately before performing a CHECK_INIT. Choice
|
||||||
|
2 is implemented here due to its simplicity. */
|
||||||
|
if (fp->_bf._base == NULL)
|
||||||
|
return 0;
|
||||||
|
#endif /* _REENT_SMALL */
|
||||||
|
|
||||||
|
CHECK_INIT (ptr, fp);
|
||||||
|
|
||||||
|
if (!fp->_flags)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
_flockfile (fp);
|
||||||
|
ret = __sflush_r (ptr, fp);
|
||||||
|
_funlockfile (fp);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef _REENT_ONLY
|
#ifndef _REENT_ONLY
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
|
@ -93,11 +93,9 @@ _DEFUN(fgetc, (fp),
|
||||||
#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__)
|
#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__)
|
||||||
int result;
|
int result;
|
||||||
CHECK_INIT(_REENT, fp);
|
CHECK_INIT(_REENT, fp);
|
||||||
__sfp_lock_acquire ();
|
|
||||||
_flockfile (fp);
|
_flockfile (fp);
|
||||||
result = __sgetc_r (_REENT, fp);
|
result = __sgetc_r (_REENT, fp);
|
||||||
_funlockfile (fp);
|
_funlockfile (fp);
|
||||||
__sfp_lock_release ();
|
|
||||||
return result;
|
return result;
|
||||||
#else
|
#else
|
||||||
return _fgetc_r (_REENT, fp);
|
return _fgetc_r (_REENT, fp);
|
||||||
|
|
|
@ -98,7 +98,6 @@ _DEFUN(_fgets_r, (ptr, buf, n, fp),
|
||||||
|
|
||||||
CHECK_INIT(ptr, fp);
|
CHECK_INIT(ptr, fp);
|
||||||
|
|
||||||
__sfp_lock_acquire ();
|
|
||||||
_flockfile (fp);
|
_flockfile (fp);
|
||||||
#ifdef __SCLE
|
#ifdef __SCLE
|
||||||
if (fp->_flags & __SCLE)
|
if (fp->_flags & __SCLE)
|
||||||
|
@ -114,12 +113,10 @@ _DEFUN(_fgets_r, (ptr, buf, n, fp),
|
||||||
if (c == EOF && s == buf)
|
if (c == EOF && s == buf)
|
||||||
{
|
{
|
||||||
_funlockfile (fp);
|
_funlockfile (fp);
|
||||||
__sfp_lock_release ();
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
*s = 0;
|
*s = 0;
|
||||||
_funlockfile (fp);
|
_funlockfile (fp);
|
||||||
__sfp_lock_release ();
|
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -138,7 +135,6 @@ _DEFUN(_fgets_r, (ptr, buf, n, fp),
|
||||||
if (s == buf)
|
if (s == buf)
|
||||||
{
|
{
|
||||||
_funlockfile (fp);
|
_funlockfile (fp);
|
||||||
__sfp_lock_release ();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -164,7 +160,6 @@ _DEFUN(_fgets_r, (ptr, buf, n, fp),
|
||||||
_CAST_VOID memcpy ((_PTR) s, (_PTR) p, len);
|
_CAST_VOID memcpy ((_PTR) s, (_PTR) p, len);
|
||||||
s[len] = 0;
|
s[len] = 0;
|
||||||
_funlockfile (fp);
|
_funlockfile (fp);
|
||||||
__sfp_lock_release ();
|
|
||||||
return (buf);
|
return (buf);
|
||||||
}
|
}
|
||||||
fp->_r -= len;
|
fp->_r -= len;
|
||||||
|
@ -175,7 +170,6 @@ _DEFUN(_fgets_r, (ptr, buf, n, fp),
|
||||||
while ((n -= len) != 0);
|
while ((n -= len) != 0);
|
||||||
*s = 0;
|
*s = 0;
|
||||||
_funlockfile (fp);
|
_funlockfile (fp);
|
||||||
__sfp_lock_release ();
|
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -164,12 +164,10 @@ _DEFUN(_fgetwc_r, (ptr, fp),
|
||||||
{
|
{
|
||||||
wint_t r;
|
wint_t r;
|
||||||
|
|
||||||
__sfp_lock_acquire ();
|
|
||||||
_flockfile (fp);
|
_flockfile (fp);
|
||||||
ORIENT(fp, 1);
|
ORIENT(fp, 1);
|
||||||
r = __fgetwc (ptr, fp);
|
r = __fgetwc (ptr, fp);
|
||||||
_funlockfile (fp);
|
_funlockfile (fp);
|
||||||
__sfp_lock_release ();
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -93,7 +93,6 @@ _DEFUN(_fgetws_r, (ptr, ws, n, fp),
|
||||||
const char *src;
|
const char *src;
|
||||||
unsigned char *nl;
|
unsigned char *nl;
|
||||||
|
|
||||||
__sfp_lock_acquire ();
|
|
||||||
_flockfile (fp);
|
_flockfile (fp);
|
||||||
ORIENT (fp, 1);
|
ORIENT (fp, 1);
|
||||||
|
|
||||||
|
@ -144,12 +143,10 @@ _DEFUN(_fgetws_r, (ptr, ws, n, fp),
|
||||||
goto error;
|
goto error;
|
||||||
*wsp++ = L'\0';
|
*wsp++ = L'\0';
|
||||||
_funlockfile (fp);
|
_funlockfile (fp);
|
||||||
__sfp_lock_release ();
|
|
||||||
return ws;
|
return ws;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
_funlockfile (fp);
|
_funlockfile (fp);
|
||||||
__sfp_lock_release ();
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -146,7 +146,6 @@ _DEFUN(_fread_r, (ptr, buf, size, count, fp),
|
||||||
|
|
||||||
CHECK_INIT(ptr, fp);
|
CHECK_INIT(ptr, fp);
|
||||||
|
|
||||||
__sfp_lock_acquire ();
|
|
||||||
_flockfile (fp);
|
_flockfile (fp);
|
||||||
ORIENT (fp, -1);
|
ORIENT (fp, -1);
|
||||||
if (fp->_r < 0)
|
if (fp->_r < 0)
|
||||||
|
@ -197,12 +196,10 @@ _DEFUN(_fread_r, (ptr, buf, size, count, fp),
|
||||||
if (fp->_flags & __SCLE)
|
if (fp->_flags & __SCLE)
|
||||||
{
|
{
|
||||||
_funlockfile (fp);
|
_funlockfile (fp);
|
||||||
__sfp_lock_release ();
|
|
||||||
return crlf_r (ptr, fp, buf, total-resid, 1) / size;
|
return crlf_r (ptr, fp, buf, total-resid, 1) / size;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
_funlockfile (fp);
|
_funlockfile (fp);
|
||||||
__sfp_lock_release ();
|
|
||||||
return (total - resid) / size;
|
return (total - resid) / size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -224,12 +221,10 @@ _DEFUN(_fread_r, (ptr, buf, size, count, fp),
|
||||||
if (fp->_flags & __SCLE)
|
if (fp->_flags & __SCLE)
|
||||||
{
|
{
|
||||||
_funlockfile (fp);
|
_funlockfile (fp);
|
||||||
__sfp_lock_release ();
|
|
||||||
return crlf_r (ptr, fp, buf, total-resid, 1) / size;
|
return crlf_r (ptr, fp, buf, total-resid, 1) / size;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
_funlockfile (fp);
|
_funlockfile (fp);
|
||||||
__sfp_lock_release ();
|
|
||||||
return (total - resid) / size;
|
return (total - resid) / size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -243,12 +238,10 @@ _DEFUN(_fread_r, (ptr, buf, size, count, fp),
|
||||||
if (fp->_flags & __SCLE)
|
if (fp->_flags & __SCLE)
|
||||||
{
|
{
|
||||||
_funlockfile (fp);
|
_funlockfile (fp);
|
||||||
__sfp_lock_release ();
|
|
||||||
return crlf_r(ptr, fp, buf, total, 0) / size;
|
return crlf_r(ptr, fp, buf, total, 0) / size;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
_funlockfile (fp);
|
_funlockfile (fp);
|
||||||
__sfp_lock_release ();
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -98,8 +98,6 @@ _DEFUN(_freopen_r, (ptr, file, mode, fp),
|
||||||
int flags, oflags;
|
int flags, oflags;
|
||||||
int e = 0;
|
int e = 0;
|
||||||
|
|
||||||
__sfp_lock_acquire ();
|
|
||||||
|
|
||||||
CHECK_INIT (ptr, fp);
|
CHECK_INIT (ptr, fp);
|
||||||
|
|
||||||
_flockfile (fp);
|
_flockfile (fp);
|
||||||
|
@ -108,7 +106,6 @@ _DEFUN(_freopen_r, (ptr, file, mode, fp),
|
||||||
{
|
{
|
||||||
_funlockfile (fp);
|
_funlockfile (fp);
|
||||||
_fclose_r (ptr, fp);
|
_fclose_r (ptr, fp);
|
||||||
__sfp_lock_release ();
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,6 +205,7 @@ _DEFUN(_freopen_r, (ptr, file, mode, fp),
|
||||||
|
|
||||||
if (f < 0)
|
if (f < 0)
|
||||||
{ /* did not get it after all */
|
{ /* did not get it after all */
|
||||||
|
__sfp_lock_acquire ();
|
||||||
fp->_flags = 0; /* set it free */
|
fp->_flags = 0; /* set it free */
|
||||||
ptr->_errno = e; /* restore in case _close clobbered */
|
ptr->_errno = e; /* restore in case _close clobbered */
|
||||||
_funlockfile (fp);
|
_funlockfile (fp);
|
||||||
|
@ -232,7 +230,6 @@ _DEFUN(_freopen_r, (ptr, file, mode, fp),
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_funlockfile (fp);
|
_funlockfile (fp);
|
||||||
__sfp_lock_release ();
|
|
||||||
return fp;
|
return fp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -138,7 +138,6 @@ _DEFUN(_fseek_r, (ptr, fp, offset, whence),
|
||||||
|
|
||||||
CHECK_INIT (ptr, fp);
|
CHECK_INIT (ptr, fp);
|
||||||
|
|
||||||
__sfp_lock_acquire ();
|
|
||||||
_flockfile (fp);
|
_flockfile (fp);
|
||||||
|
|
||||||
/* If we've been doing some writing, and we're in append mode
|
/* If we've been doing some writing, and we're in append mode
|
||||||
|
@ -156,7 +155,6 @@ _DEFUN(_fseek_r, (ptr, fp, offset, whence),
|
||||||
{
|
{
|
||||||
ptr->_errno = ESPIPE; /* ??? */
|
ptr->_errno = ESPIPE; /* ??? */
|
||||||
_funlockfile (fp);
|
_funlockfile (fp);
|
||||||
__sfp_lock_release ();
|
|
||||||
return EOF;
|
return EOF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,7 +180,6 @@ _DEFUN(_fseek_r, (ptr, fp, offset, whence),
|
||||||
if (curoff == -1L)
|
if (curoff == -1L)
|
||||||
{
|
{
|
||||||
_funlockfile (fp);
|
_funlockfile (fp);
|
||||||
__sfp_lock_release ();
|
|
||||||
return EOF;
|
return EOF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -208,7 +205,6 @@ _DEFUN(_fseek_r, (ptr, fp, offset, whence),
|
||||||
default:
|
default:
|
||||||
ptr->_errno = EINVAL;
|
ptr->_errno = EINVAL;
|
||||||
_funlockfile (fp);
|
_funlockfile (fp);
|
||||||
__sfp_lock_release ();
|
|
||||||
return (EOF);
|
return (EOF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,7 +264,6 @@ _DEFUN(_fseek_r, (ptr, fp, offset, whence),
|
||||||
{
|
{
|
||||||
ptr->_errno = EOVERFLOW;
|
ptr->_errno = EOVERFLOW;
|
||||||
_funlockfile (fp);
|
_funlockfile (fp);
|
||||||
__sfp_lock_release ();
|
|
||||||
return EOF;
|
return EOF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,7 +320,6 @@ _DEFUN(_fseek_r, (ptr, fp, offset, whence),
|
||||||
fp->_flags &= ~__SEOF;
|
fp->_flags &= ~__SEOF;
|
||||||
memset (&fp->_mbstate, 0, sizeof (_mbstate_t));
|
memset (&fp->_mbstate, 0, sizeof (_mbstate_t));
|
||||||
_funlockfile (fp);
|
_funlockfile (fp);
|
||||||
__sfp_lock_release ();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -356,7 +350,6 @@ _DEFUN(_fseek_r, (ptr, fp, offset, whence),
|
||||||
}
|
}
|
||||||
memset (&fp->_mbstate, 0, sizeof (_mbstate_t));
|
memset (&fp->_mbstate, 0, sizeof (_mbstate_t));
|
||||||
_funlockfile (fp);
|
_funlockfile (fp);
|
||||||
__sfp_lock_release ();
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -369,7 +362,6 @@ dumb:
|
||||||
|| seekfn (ptr, fp->_cookie, offset, whence) == POS_ERR)
|
|| seekfn (ptr, fp->_cookie, offset, whence) == POS_ERR)
|
||||||
{
|
{
|
||||||
_funlockfile (fp);
|
_funlockfile (fp);
|
||||||
__sfp_lock_release ();
|
|
||||||
return EOF;
|
return EOF;
|
||||||
}
|
}
|
||||||
/* success: clear EOF indicator and discard ungetc() data */
|
/* success: clear EOF indicator and discard ungetc() data */
|
||||||
|
@ -388,7 +380,6 @@ dumb:
|
||||||
fp->_flags &= ~__SNPT;
|
fp->_flags &= ~__SNPT;
|
||||||
memset (&fp->_mbstate, 0, sizeof (_mbstate_t));
|
memset (&fp->_mbstate, 0, sizeof (_mbstate_t));
|
||||||
_funlockfile (fp);
|
_funlockfile (fp);
|
||||||
__sfp_lock_release ();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,8 +27,8 @@ static char sccsid[] = "%W% (Berkeley) %G%";
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include "local.h"
|
#include "local.h"
|
||||||
|
|
||||||
static int
|
int
|
||||||
_DEFUN(__fwalk, (ptr, function),
|
_DEFUN(_fwalk, (ptr, function),
|
||||||
struct _reent *ptr _AND
|
struct _reent *ptr _AND
|
||||||
register int (*function) (FILE *))
|
register int (*function) (FILE *))
|
||||||
{
|
{
|
||||||
|
@ -36,11 +36,19 @@ _DEFUN(__fwalk, (ptr, function),
|
||||||
register int n, ret = 0;
|
register int n, ret = 0;
|
||||||
register struct _glue *g;
|
register struct _glue *g;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* It should be safe to walk the list without locking it;
|
||||||
|
* new nodes are only added to the end and none are ever
|
||||||
|
* removed.
|
||||||
|
*
|
||||||
|
* Avoid locking this list while walking it or else you will
|
||||||
|
* introduce a potential deadlock in [at least] refill.c.
|
||||||
|
*/
|
||||||
for (g = &ptr->__sglue; g != NULL; g = g->_next)
|
for (g = &ptr->__sglue; g != NULL; g = g->_next)
|
||||||
for (fp = g->_iobs, n = g->_niobs; --n >= 0; fp++)
|
for (fp = g->_iobs, n = g->_niobs; --n >= 0; fp++)
|
||||||
if (fp->_flags != 0)
|
if (fp->_flags != 0)
|
||||||
{
|
{
|
||||||
if (fp->_flags != 0 && fp->_file != -1)
|
if (fp->_flags != 0 && fp->_flags != 1 && fp->_file != -1)
|
||||||
ret |= (*function) (fp);
|
ret |= (*function) (fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,8 +57,8 @@ _DEFUN(__fwalk, (ptr, function),
|
||||||
|
|
||||||
/* Special version of __fwalk where the function pointer is a reentrant
|
/* Special version of __fwalk where the function pointer is a reentrant
|
||||||
I/O function (e.g. _fclose_r). */
|
I/O function (e.g. _fclose_r). */
|
||||||
static int
|
int
|
||||||
_DEFUN(__fwalk_reent, (ptr, reent_function),
|
_DEFUN(_fwalk_reent, (ptr, reent_function),
|
||||||
struct _reent *ptr _AND
|
struct _reent *ptr _AND
|
||||||
register int (*reent_function) (struct _reent *, FILE *))
|
register int (*reent_function) (struct _reent *, FILE *))
|
||||||
{
|
{
|
||||||
|
@ -58,51 +66,21 @@ _DEFUN(__fwalk_reent, (ptr, reent_function),
|
||||||
register int n, ret = 0;
|
register int n, ret = 0;
|
||||||
register struct _glue *g;
|
register struct _glue *g;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* It should be safe to walk the list without locking it;
|
||||||
|
* new nodes are only added to the end and none are ever
|
||||||
|
* removed.
|
||||||
|
*
|
||||||
|
* Avoid locking this list while walking it or else you will
|
||||||
|
* introduce a potential deadlock in [at least] refill.c.
|
||||||
|
*/
|
||||||
for (g = &ptr->__sglue; g != NULL; g = g->_next)
|
for (g = &ptr->__sglue; g != NULL; g = g->_next)
|
||||||
for (fp = g->_iobs, n = g->_niobs; --n >= 0; fp++)
|
for (fp = g->_iobs, n = g->_niobs; --n >= 0; fp++)
|
||||||
if (fp->_flags != 0)
|
if (fp->_flags != 0)
|
||||||
{
|
{
|
||||||
if (fp->_flags != 0 && fp->_file != -1)
|
if (fp->_flags != 0 && fp->_flags != 1 && fp->_file != -1)
|
||||||
ret |= (*reent_function) (ptr, fp);
|
ret |= (*reent_function) (ptr, fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
_DEFUN(_fwalk, (ptr, function),
|
|
||||||
struct _reent *ptr _AND
|
|
||||||
register int (*function)(FILE *))
|
|
||||||
{
|
|
||||||
register int ret = 0;
|
|
||||||
|
|
||||||
__sfp_lock_acquire ();
|
|
||||||
|
|
||||||
/* Must traverse given list for streams. Note that _GLOBAL_REENT
|
|
||||||
only walked once in exit(). */
|
|
||||||
ret |= __fwalk (ptr, function);
|
|
||||||
|
|
||||||
__sfp_lock_release ();
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Special version of _fwalk which handles a function pointer to a
|
|
||||||
reentrant I/O function (e.g. _fclose_r). */
|
|
||||||
int
|
|
||||||
_DEFUN(_fwalk_reent, (ptr, reent_function),
|
|
||||||
struct _reent *ptr _AND
|
|
||||||
register int (*reent_function) (struct _reent *, FILE *))
|
|
||||||
{
|
|
||||||
register int ret = 0;
|
|
||||||
|
|
||||||
__sfp_lock_acquire ();
|
|
||||||
|
|
||||||
/* Must traverse given list for streams. Note that _GLOBAL_REENT
|
|
||||||
only walked once in exit(). */
|
|
||||||
ret |= __fwalk_reent (ptr, reent_function);
|
|
||||||
|
|
||||||
__sfp_lock_release ();
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
|
@ -92,11 +92,9 @@ _DEFUN(_getc_r, (ptr, fp),
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
CHECK_INIT (ptr, fp);
|
CHECK_INIT (ptr, fp);
|
||||||
__sfp_lock_acquire ();
|
|
||||||
_flockfile (fp);
|
_flockfile (fp);
|
||||||
result = __sgetc_r (ptr, fp);
|
result = __sgetc_r (ptr, fp);
|
||||||
_funlockfile (fp);
|
_funlockfile (fp);
|
||||||
__sfp_lock_release ();
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,11 +106,9 @@ _DEFUN(getc, (fp),
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
CHECK_INIT (_REENT, fp);
|
CHECK_INIT (_REENT, fp);
|
||||||
__sfp_lock_acquire ();
|
|
||||||
_flockfile (fp);
|
_flockfile (fp);
|
||||||
result = __sgetc_r (_REENT, fp);
|
result = __sgetc_r (_REENT, fp);
|
||||||
_funlockfile (fp);
|
_funlockfile (fp);
|
||||||
__sfp_lock_release ();
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -81,7 +81,6 @@ _DEFUN(__getdelim, (bufptr, n, delim, fp),
|
||||||
|
|
||||||
CHECK_INIT (_REENT, fp);
|
CHECK_INIT (_REENT, fp);
|
||||||
|
|
||||||
__sfp_lock_acquire ();
|
|
||||||
_flockfile (fp);
|
_flockfile (fp);
|
||||||
|
|
||||||
numbytes = *n;
|
numbytes = *n;
|
||||||
|
@ -131,7 +130,6 @@ _DEFUN(__getdelim, (bufptr, n, delim, fp),
|
||||||
}
|
}
|
||||||
|
|
||||||
_funlockfile (fp);
|
_funlockfile (fp);
|
||||||
__sfp_lock_release ();
|
|
||||||
|
|
||||||
/* if no input data, return failure */
|
/* if no input data, return failure */
|
||||||
if (ptr == buf)
|
if (ptr == buf)
|
||||||
|
|
|
@ -79,14 +79,12 @@ _DEFUN(_gets_r, (ptr, buf),
|
||||||
register int c;
|
register int c;
|
||||||
register char *s = buf;
|
register char *s = buf;
|
||||||
|
|
||||||
__sfp_lock_acquire ();
|
|
||||||
_flockfile (stdin);
|
_flockfile (stdin);
|
||||||
while ((c = __sgetc_r (ptr, stdin)) != '\n')
|
while ((c = __sgetc_r (ptr, stdin)) != '\n')
|
||||||
if (c == EOF)
|
if (c == EOF)
|
||||||
if (s == buf)
|
if (s == buf)
|
||||||
{
|
{
|
||||||
_funlockfile (stdin);
|
_funlockfile (stdin);
|
||||||
__sfp_lock_release ();
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -95,7 +93,6 @@ _DEFUN(_gets_r, (ptr, buf),
|
||||||
*s++ = c;
|
*s++ = c;
|
||||||
*s = 0;
|
*s = 0;
|
||||||
_funlockfile (stdin);
|
_funlockfile (stdin);
|
||||||
__sfp_lock_release ();
|
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,6 +54,7 @@ int _EXFUN(_svfiwprintf_r,(struct _reent *, FILE *, const wchar_t *,
|
||||||
va_list));
|
va_list));
|
||||||
extern FILE *_EXFUN(__sfp,(struct _reent *));
|
extern FILE *_EXFUN(__sfp,(struct _reent *));
|
||||||
extern int _EXFUN(__sflags,(struct _reent *,_CONST char*, int*));
|
extern int _EXFUN(__sflags,(struct _reent *,_CONST char*, int*));
|
||||||
|
extern int _EXFUN(__sflush_r,(struct _reent *,FILE *));
|
||||||
extern int _EXFUN(__srefill_r,(struct _reent *,FILE *));
|
extern int _EXFUN(__srefill_r,(struct _reent *,FILE *));
|
||||||
extern _READ_WRITE_RETURN_TYPE _EXFUN(__sread,(struct _reent *, void *, char *,
|
extern _READ_WRITE_RETURN_TYPE _EXFUN(__sread,(struct _reent *, void *, char *,
|
||||||
int));
|
int));
|
||||||
|
|
|
@ -102,9 +102,19 @@ _DEFUN(__srefill_r, (ptr, fp),
|
||||||
* flush all line buffered output files, per the ANSI C
|
* flush all line buffered output files, per the ANSI C
|
||||||
* standard.
|
* standard.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (fp->_flags & (__SLBF | __SNBF))
|
if (fp->_flags & (__SLBF | __SNBF))
|
||||||
|
{
|
||||||
|
/* Ignore this file in _fwalk to avoid potential deadlock. */
|
||||||
|
short orig_flags = fp->_flags;
|
||||||
|
fp->_flags = 1;
|
||||||
_CAST_VOID _fwalk (_GLOBAL_REENT, lflush);
|
_CAST_VOID _fwalk (_GLOBAL_REENT, lflush);
|
||||||
|
fp->_flags = orig_flags;
|
||||||
|
|
||||||
|
/* Now flush this file without locking it. */
|
||||||
|
if ((fp->_flags & (__SLBF|__SWR)) == (__SLBF|__SWR))
|
||||||
|
__sflush_r (ptr, fp);
|
||||||
|
}
|
||||||
|
|
||||||
fp->_p = fp->_bf._base;
|
fp->_p = fp->_bf._base;
|
||||||
fp->_r = fp->_read (ptr, fp->_cookie, (char *) fp->_p, fp->_bf._size);
|
fp->_r = fp->_read (ptr, fp->_cookie, (char *) fp->_p, fp->_bf._size);
|
||||||
#ifndef __CYGWIN__
|
#ifndef __CYGWIN__
|
||||||
|
|
|
@ -494,7 +494,6 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
|
||||||
# define GET_ARG(n, ap, type) (va_arg (ap, type))
|
# define GET_ARG(n, ap, type) (va_arg (ap, type))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
__sfp_lock_acquire ();
|
|
||||||
_flockfile (fp);
|
_flockfile (fp);
|
||||||
|
|
||||||
ORIENT (fp, -1);
|
ORIENT (fp, -1);
|
||||||
|
@ -795,7 +794,6 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
|
||||||
*/
|
*/
|
||||||
case '\0': /* compat */
|
case '\0': /* compat */
|
||||||
_funlockfile (fp);
|
_funlockfile (fp);
|
||||||
__sfp_lock_release ();
|
|
||||||
return EOF;
|
return EOF;
|
||||||
|
|
||||||
default: /* compat */
|
default: /* compat */
|
||||||
|
@ -1596,13 +1594,11 @@ input_failure:
|
||||||
invalid format string), return EOF if no matches yet, else number
|
invalid format string), return EOF if no matches yet, else number
|
||||||
of matches made prior to failure. */
|
of matches made prior to failure. */
|
||||||
_funlockfile (fp);
|
_funlockfile (fp);
|
||||||
__sfp_lock_release ();
|
|
||||||
return nassigned && !(fp->_flags & __SERR) ? nassigned : EOF;
|
return nassigned && !(fp->_flags & __SERR) ? nassigned : EOF;
|
||||||
match_failure:
|
match_failure:
|
||||||
all_done:
|
all_done:
|
||||||
/* Return number of matches, which can be 0 on match failure. */
|
/* Return number of matches, which can be 0 on match failure. */
|
||||||
_funlockfile (fp);
|
_funlockfile (fp);
|
||||||
__sfp_lock_release ();
|
|
||||||
return nassigned;
|
return nassigned;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -434,7 +434,6 @@ _DEFUN(__SVFWSCANF_R, (rptr, fp, fmt0, ap),
|
||||||
# define GET_ARG(n, ap, type) (va_arg (ap, type))
|
# define GET_ARG(n, ap, type) (va_arg (ap, type))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
__sfp_lock_acquire ();
|
|
||||||
_flockfile (fp);
|
_flockfile (fp);
|
||||||
|
|
||||||
ORIENT (fp, 1);
|
ORIENT (fp, 1);
|
||||||
|
@ -714,7 +713,6 @@ _DEFUN(__SVFWSCANF_R, (rptr, fp, fmt0, ap),
|
||||||
*/
|
*/
|
||||||
case L'\0': /* compat */
|
case L'\0': /* compat */
|
||||||
_funlockfile (fp);
|
_funlockfile (fp);
|
||||||
__sfp_lock_release ();
|
|
||||||
return EOF;
|
return EOF;
|
||||||
|
|
||||||
default: /* compat */
|
default: /* compat */
|
||||||
|
@ -1443,13 +1441,11 @@ input_failure:
|
||||||
invalid format string), return EOF if no matches yet, else number
|
invalid format string), return EOF if no matches yet, else number
|
||||||
of matches made prior to failure. */
|
of matches made prior to failure. */
|
||||||
_funlockfile (fp);
|
_funlockfile (fp);
|
||||||
__sfp_lock_release ();
|
|
||||||
return nassigned && !(fp->_flags & __SERR) ? nassigned : EOF;
|
return nassigned && !(fp->_flags & __SERR) ? nassigned : EOF;
|
||||||
match_failure:
|
match_failure:
|
||||||
all_done:
|
all_done:
|
||||||
/* Return number of matches, which can be 0 on match failure. */
|
/* Return number of matches, which can be 0 on match failure. */
|
||||||
_funlockfile (fp);
|
_funlockfile (fp);
|
||||||
__sfp_lock_release ();
|
|
||||||
return nassigned;
|
return nassigned;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -97,7 +97,6 @@ _DEFUN (_freopen64_r, (ptr, file, mode, fp),
|
||||||
int flags, oflags;
|
int flags, oflags;
|
||||||
int e = 0;
|
int e = 0;
|
||||||
|
|
||||||
__sfp_lock_acquire ();
|
|
||||||
|
|
||||||
CHECK_INIT (ptr, fp);
|
CHECK_INIT (ptr, fp);
|
||||||
|
|
||||||
|
@ -107,7 +106,6 @@ _DEFUN (_freopen64_r, (ptr, file, mode, fp),
|
||||||
{
|
{
|
||||||
_funlockfile(fp);
|
_funlockfile(fp);
|
||||||
_fclose_r (ptr, fp);
|
_fclose_r (ptr, fp);
|
||||||
__sfp_lock_release ();
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,6 +202,7 @@ _DEFUN (_freopen64_r, (ptr, file, mode, fp),
|
||||||
|
|
||||||
if (f < 0)
|
if (f < 0)
|
||||||
{ /* did not get it after all */
|
{ /* did not get it after all */
|
||||||
|
__sfp_lock_acquire ();
|
||||||
fp->_flags = 0; /* set it free */
|
fp->_flags = 0; /* set it free */
|
||||||
ptr->_errno = e; /* restore in case _close clobbered */
|
ptr->_errno = e; /* restore in case _close clobbered */
|
||||||
_funlockfile(fp);
|
_funlockfile(fp);
|
||||||
|
@ -231,7 +230,6 @@ _DEFUN (_freopen64_r, (ptr, file, mode, fp),
|
||||||
fp->_flags |= __SL64;
|
fp->_flags |= __SL64;
|
||||||
|
|
||||||
_funlockfile(fp);
|
_funlockfile(fp);
|
||||||
__sfp_lock_release ();
|
|
||||||
return fp;
|
return fp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue