summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2011-01-28 10:49:11 +0000
committerCorinna Vinschen <corinna@vinschen.de>2011-01-28 10:49:11 +0000
commit656df313e08a9ac4ef33c553285bb52d23c3e15f (patch)
tree5288836d1861c764410741e9b300ce21c3627aba
parentb5ca0d72711a691b733e64a7ea8cb93ef1d8d98e (diff)
downloadcygnal-656df313e08a9ac4ef33c553285bb52d23c3e15f.tar.gz
cygnal-656df313e08a9ac4ef33c553285bb52d23c3e15f.tar.bz2
cygnal-656df313e08a9ac4ef33c553285bb52d23c3e15f.zip
* 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.
-rw-r--r--newlib/ChangeLog31
-rw-r--r--newlib/libc/stdio/fclose.c4
-rw-r--r--newlib/libc/stdio/fflush.c67
-rw-r--r--newlib/libc/stdio/fgetc.c2
-rw-r--r--newlib/libc/stdio/fgets.c6
-rw-r--r--newlib/libc/stdio/fgetwc.c2
-rw-r--r--newlib/libc/stdio/fgetws.c3
-rw-r--r--newlib/libc/stdio/fread.c7
-rw-r--r--newlib/libc/stdio/freopen.c5
-rw-r--r--newlib/libc/stdio/fseek.c9
-rw-r--r--newlib/libc/stdio/fwalk.c66
-rw-r--r--newlib/libc/stdio/getc.c4
-rw-r--r--newlib/libc/stdio/getdelim.c2
-rw-r--r--newlib/libc/stdio/gets.c3
-rw-r--r--newlib/libc/stdio/local.h1
-rw-r--r--newlib/libc/stdio/refill.c14
-rw-r--r--newlib/libc/stdio/vfscanf.c4
-rw-r--r--newlib/libc/stdio/vfwscanf.c4
-rw-r--r--newlib/libc/stdio64/freopen64.c4
19 files changed, 106 insertions, 132 deletions
diff --git a/newlib/ChangeLog b/newlib/ChangeLog
index 5fff8adbc..d1da3833f 100644
--- a/newlib/ChangeLog
+++ b/newlib/ChangeLog
@@ -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>
* libc/include/sys/features.h: Define __STDC_ISO_10646__ for Cygwin.
diff --git a/newlib/libc/stdio/fclose.c b/newlib/libc/stdio/fclose.c
index a14a63f3f..3c8868a51 100644
--- a/newlib/libc/stdio/fclose.c
+++ b/newlib/libc/stdio/fclose.c
@@ -74,8 +74,6 @@ _DEFUN(_fclose_r, (rptr, fp),
if (fp == NULL)
return (0); /* on NULL */
- __sfp_lock_acquire ();
-
CHECK_INIT (rptr, fp);
_flockfile (fp);
@@ -83,7 +81,6 @@ _DEFUN(_fclose_r, (rptr, fp),
if (fp->_flags == 0) /* not open! */
{
_funlockfile (fp);
- __sfp_lock_release ();
return (0);
}
/* Unconditionally flush to allow special handling for seekable read
@@ -98,6 +95,7 @@ _DEFUN(_fclose_r, (rptr, fp),
FREEUB (rptr, fp);
if (HASLB (fp))
FREELB (rptr, fp);
+ __sfp_lock_acquire ();
fp->_flags = 0; /* release this FILE for reuse */
_funlockfile (fp);
#ifndef __SINGLE_THREAD__
diff --git a/newlib/libc/stdio/fflush.c b/newlib/libc/stdio/fflush.c
index ea6d2fb18..130c148c9 100644
--- a/newlib/libc/stdio/fflush.c
+++ b/newlib/libc/stdio/fflush.c
@@ -67,37 +67,16 @@ No supporting OS subroutines are required.
/* 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
-_DEFUN(_fflush_r, (ptr, fp),
+_DEFUN(__sflush_r, (ptr, fp),
struct _reent *ptr _AND
register FILE * fp)
{
register unsigned char *p;
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;
if ((t & __SWR) == 0)
{
@@ -150,7 +129,6 @@ _DEFUN(_fflush_r, (ptr, fp),
}
else
fp->_flags |= __SERR;
- _funlockfile (fp);
return result;
}
}
@@ -186,17 +164,14 @@ _DEFUN(_fflush_r, (ptr, fp),
else
{
fp->_flags |= __SERR;
- _funlockfile (fp);
return EOF;
}
}
- _funlockfile (fp);
return 0;
}
if ((p = fp->_bf._base) == NULL)
{
/* Nothing to flush. */
- _funlockfile (fp);
return 0;
}
n = fp->_p - p; /* write this much */
@@ -215,16 +190,48 @@ _DEFUN(_fflush_r, (ptr, fp),
if (t <= 0)
{
fp->_flags |= __SERR;
- _funlockfile (fp);
return EOF;
}
p += t;
n -= t;
}
- _funlockfile (fp);
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
int
diff --git a/newlib/libc/stdio/fgetc.c b/newlib/libc/stdio/fgetc.c
index 9837a2ebc..e275cfeeb 100644
--- a/newlib/libc/stdio/fgetc.c
+++ b/newlib/libc/stdio/fgetc.c
@@ -93,11 +93,9 @@ _DEFUN(fgetc, (fp),
#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__)
int result;
CHECK_INIT(_REENT, fp);
- __sfp_lock_acquire ();
_flockfile (fp);
result = __sgetc_r (_REENT, fp);
_funlockfile (fp);
- __sfp_lock_release ();
return result;
#else
return _fgetc_r (_REENT, fp);
diff --git a/newlib/libc/stdio/fgets.c b/newlib/libc/stdio/fgets.c
index 21bfdd4c6..7f02e3fcb 100644
--- a/newlib/libc/stdio/fgets.c
+++ b/newlib/libc/stdio/fgets.c
@@ -98,7 +98,6 @@ _DEFUN(_fgets_r, (ptr, buf, n, fp),
CHECK_INIT(ptr, fp);
- __sfp_lock_acquire ();
_flockfile (fp);
#ifdef __SCLE
if (fp->_flags & __SCLE)
@@ -114,12 +113,10 @@ _DEFUN(_fgets_r, (ptr, buf, n, fp),
if (c == EOF && s == buf)
{
_funlockfile (fp);
- __sfp_lock_release ();
return NULL;
}
*s = 0;
_funlockfile (fp);
- __sfp_lock_release ();
return buf;
}
#endif
@@ -138,7 +135,6 @@ _DEFUN(_fgets_r, (ptr, buf, n, fp),
if (s == buf)
{
_funlockfile (fp);
- __sfp_lock_release ();
return 0;
}
break;
@@ -164,7 +160,6 @@ _DEFUN(_fgets_r, (ptr, buf, n, fp),
_CAST_VOID memcpy ((_PTR) s, (_PTR) p, len);
s[len] = 0;
_funlockfile (fp);
- __sfp_lock_release ();
return (buf);
}
fp->_r -= len;
@@ -175,7 +170,6 @@ _DEFUN(_fgets_r, (ptr, buf, n, fp),
while ((n -= len) != 0);
*s = 0;
_funlockfile (fp);
- __sfp_lock_release ();
return buf;
}
diff --git a/newlib/libc/stdio/fgetwc.c b/newlib/libc/stdio/fgetwc.c
index f4c81ddb9..38a79bc7c 100644
--- a/newlib/libc/stdio/fgetwc.c
+++ b/newlib/libc/stdio/fgetwc.c
@@ -164,12 +164,10 @@ _DEFUN(_fgetwc_r, (ptr, fp),
{
wint_t r;
- __sfp_lock_acquire ();
_flockfile (fp);
ORIENT(fp, 1);
r = __fgetwc (ptr, fp);
_funlockfile (fp);
- __sfp_lock_release ();
return r;
}
diff --git a/newlib/libc/stdio/fgetws.c b/newlib/libc/stdio/fgetws.c
index 3dbae06cb..2784f1513 100644
--- a/newlib/libc/stdio/fgetws.c
+++ b/newlib/libc/stdio/fgetws.c
@@ -93,7 +93,6 @@ _DEFUN(_fgetws_r, (ptr, ws, n, fp),
const char *src;
unsigned char *nl;
- __sfp_lock_acquire ();
_flockfile (fp);
ORIENT (fp, 1);
@@ -144,12 +143,10 @@ _DEFUN(_fgetws_r, (ptr, ws, n, fp),
goto error;
*wsp++ = L'\0';
_funlockfile (fp);
- __sfp_lock_release ();
return ws;
error:
_funlockfile (fp);
- __sfp_lock_release ();
return NULL;
}
diff --git a/newlib/libc/stdio/fread.c b/newlib/libc/stdio/fread.c
index dda2044fe..a39e9d85f 100644
--- a/newlib/libc/stdio/fread.c
+++ b/newlib/libc/stdio/fread.c
@@ -146,7 +146,6 @@ _DEFUN(_fread_r, (ptr, buf, size, count, fp),
CHECK_INIT(ptr, fp);
- __sfp_lock_acquire ();
_flockfile (fp);
ORIENT (fp, -1);
if (fp->_r < 0)
@@ -197,12 +196,10 @@ _DEFUN(_fread_r, (ptr, buf, size, count, fp),
if (fp->_flags & __SCLE)
{
_funlockfile (fp);
- __sfp_lock_release ();
return crlf_r (ptr, fp, buf, total-resid, 1) / size;
}
#endif
_funlockfile (fp);
- __sfp_lock_release ();
return (total - resid) / size;
}
}
@@ -224,12 +221,10 @@ _DEFUN(_fread_r, (ptr, buf, size, count, fp),
if (fp->_flags & __SCLE)
{
_funlockfile (fp);
- __sfp_lock_release ();
return crlf_r (ptr, fp, buf, total-resid, 1) / size;
}
#endif
_funlockfile (fp);
- __sfp_lock_release ();
return (total - resid) / size;
}
}
@@ -243,12 +238,10 @@ _DEFUN(_fread_r, (ptr, buf, size, count, fp),
if (fp->_flags & __SCLE)
{
_funlockfile (fp);
- __sfp_lock_release ();
return crlf_r(ptr, fp, buf, total, 0) / size;
}
#endif
_funlockfile (fp);
- __sfp_lock_release ();
return count;
}
diff --git a/newlib/libc/stdio/freopen.c b/newlib/libc/stdio/freopen.c
index ae774c65b..172006259 100644
--- a/newlib/libc/stdio/freopen.c
+++ b/newlib/libc/stdio/freopen.c
@@ -98,8 +98,6 @@ _DEFUN(_freopen_r, (ptr, file, mode, fp),
int flags, oflags;
int e = 0;
- __sfp_lock_acquire ();
-
CHECK_INIT (ptr, fp);
_flockfile (fp);
@@ -108,7 +106,6 @@ _DEFUN(_freopen_r, (ptr, file, mode, fp),
{
_funlockfile (fp);
_fclose_r (ptr, fp);
- __sfp_lock_release ();
return NULL;
}
@@ -208,6 +205,7 @@ _DEFUN(_freopen_r, (ptr, file, mode, fp),
if (f < 0)
{ /* did not get it after all */
+ __sfp_lock_acquire ();
fp->_flags = 0; /* set it free */
ptr->_errno = e; /* restore in case _close clobbered */
_funlockfile (fp);
@@ -232,7 +230,6 @@ _DEFUN(_freopen_r, (ptr, file, mode, fp),
#endif
_funlockfile (fp);
- __sfp_lock_release ();
return fp;
}
diff --git a/newlib/libc/stdio/fseek.c b/newlib/libc/stdio/fseek.c
index 0ba7b6ca3..c78d2b26c 100644
--- a/newlib/libc/stdio/fseek.c
+++ b/newlib/libc/stdio/fseek.c
@@ -138,7 +138,6 @@ _DEFUN(_fseek_r, (ptr, fp, offset, whence),
CHECK_INIT (ptr, fp);
- __sfp_lock_acquire ();
_flockfile (fp);
/* 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; /* ??? */
_funlockfile (fp);
- __sfp_lock_release ();
return EOF;
}
@@ -182,7 +180,6 @@ _DEFUN(_fseek_r, (ptr, fp, offset, whence),
if (curoff == -1L)
{
_funlockfile (fp);
- __sfp_lock_release ();
return EOF;
}
}
@@ -208,7 +205,6 @@ _DEFUN(_fseek_r, (ptr, fp, offset, whence),
default:
ptr->_errno = EINVAL;
_funlockfile (fp);
- __sfp_lock_release ();
return (EOF);
}
@@ -268,7 +264,6 @@ _DEFUN(_fseek_r, (ptr, fp, offset, whence),
{
ptr->_errno = EOVERFLOW;
_funlockfile (fp);
- __sfp_lock_release ();
return EOF;
}
@@ -325,7 +320,6 @@ _DEFUN(_fseek_r, (ptr, fp, offset, whence),
fp->_flags &= ~__SEOF;
memset (&fp->_mbstate, 0, sizeof (_mbstate_t));
_funlockfile (fp);
- __sfp_lock_release ();
return 0;
}
@@ -356,7 +350,6 @@ _DEFUN(_fseek_r, (ptr, fp, offset, whence),
}
memset (&fp->_mbstate, 0, sizeof (_mbstate_t));
_funlockfile (fp);
- __sfp_lock_release ();
return 0;
/*
@@ -369,7 +362,6 @@ dumb:
|| seekfn (ptr, fp->_cookie, offset, whence) == POS_ERR)
{
_funlockfile (fp);
- __sfp_lock_release ();
return EOF;
}
/* success: clear EOF indicator and discard ungetc() data */
@@ -388,7 +380,6 @@ dumb:
fp->_flags &= ~__SNPT;
memset (&fp->_mbstate, 0, sizeof (_mbstate_t));
_funlockfile (fp);
- __sfp_lock_release ();
return 0;
}
diff --git a/newlib/libc/stdio/fwalk.c b/newlib/libc/stdio/fwalk.c
index 24cbe9ac4..df92d1d81 100644
--- a/newlib/libc/stdio/fwalk.c
+++ b/newlib/libc/stdio/fwalk.c
@@ -27,8 +27,8 @@ static char sccsid[] = "%W% (Berkeley) %G%";
#include <errno.h>
#include "local.h"
-static int
-_DEFUN(__fwalk, (ptr, function),
+int
+_DEFUN(_fwalk, (ptr, function),
struct _reent *ptr _AND
register int (*function) (FILE *))
{
@@ -36,11 +36,19 @@ _DEFUN(__fwalk, (ptr, function),
register int n, ret = 0;
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 (fp = g->_iobs, n = g->_niobs; --n >= 0; fp++)
if (fp->_flags != 0)
{
- if (fp->_flags != 0 && fp->_file != -1)
+ if (fp->_flags != 0 && fp->_flags != 1 && fp->_file != -1)
ret |= (*function) (fp);
}
@@ -49,8 +57,8 @@ _DEFUN(__fwalk, (ptr, function),
/* Special version of __fwalk where the function pointer is a reentrant
I/O function (e.g. _fclose_r). */
-static int
-_DEFUN(__fwalk_reent, (ptr, reent_function),
+int
+_DEFUN(_fwalk_reent, (ptr, reent_function),
struct _reent *ptr _AND
register int (*reent_function) (struct _reent *, FILE *))
{
@@ -58,51 +66,21 @@ _DEFUN(__fwalk_reent, (ptr, reent_function),
register int n, ret = 0;
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 (fp = g->_iobs, n = g->_niobs; --n >= 0; fp++)
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);
}
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;
-}
diff --git a/newlib/libc/stdio/getc.c b/newlib/libc/stdio/getc.c
index 544ac734c..5b1fa888a 100644
--- a/newlib/libc/stdio/getc.c
+++ b/newlib/libc/stdio/getc.c
@@ -92,11 +92,9 @@ _DEFUN(_getc_r, (ptr, fp),
{
int result;
CHECK_INIT (ptr, fp);
- __sfp_lock_acquire ();
_flockfile (fp);
result = __sgetc_r (ptr, fp);
_funlockfile (fp);
- __sfp_lock_release ();
return result;
}
@@ -108,11 +106,9 @@ _DEFUN(getc, (fp),
{
int result;
CHECK_INIT (_REENT, fp);
- __sfp_lock_acquire ();
_flockfile (fp);
result = __sgetc_r (_REENT, fp);
_funlockfile (fp);
- __sfp_lock_release ();
return result;
}
diff --git a/newlib/libc/stdio/getdelim.c b/newlib/libc/stdio/getdelim.c
index 41460ab42..23fc50218 100644
--- a/newlib/libc/stdio/getdelim.c
+++ b/newlib/libc/stdio/getdelim.c
@@ -81,7 +81,6 @@ _DEFUN(__getdelim, (bufptr, n, delim, fp),
CHECK_INIT (_REENT, fp);
- __sfp_lock_acquire ();
_flockfile (fp);
numbytes = *n;
@@ -131,7 +130,6 @@ _DEFUN(__getdelim, (bufptr, n, delim, fp),
}
_funlockfile (fp);
- __sfp_lock_release ();
/* if no input data, return failure */
if (ptr == buf)
diff --git a/newlib/libc/stdio/gets.c b/newlib/libc/stdio/gets.c
index daa42e954..17d144316 100644
--- a/newlib/libc/stdio/gets.c
+++ b/newlib/libc/stdio/gets.c
@@ -79,14 +79,12 @@ _DEFUN(_gets_r, (ptr, buf),
register int c;
register char *s = buf;
- __sfp_lock_acquire ();
_flockfile (stdin);
while ((c = __sgetc_r (ptr, stdin)) != '\n')
if (c == EOF)
if (s == buf)
{
_funlockfile (stdin);
- __sfp_lock_release ();
return NULL;
}
else
@@ -95,7 +93,6 @@ _DEFUN(_gets_r, (ptr, buf),
*s++ = c;
*s = 0;
_funlockfile (stdin);
- __sfp_lock_release ();
return buf;
}
diff --git a/newlib/libc/stdio/local.h b/newlib/libc/stdio/local.h
index b69524c57..9ca948d96 100644
--- a/newlib/libc/stdio/local.h
+++ b/newlib/libc/stdio/local.h
@@ -54,6 +54,7 @@ int _EXFUN(_svfiwprintf_r,(struct _reent *, FILE *, const wchar_t *,
va_list));
extern FILE *_EXFUN(__sfp,(struct _reent *));
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 _READ_WRITE_RETURN_TYPE _EXFUN(__sread,(struct _reent *, void *, char *,
int));
diff --git a/newlib/libc/stdio/refill.c b/newlib/libc/stdio/refill.c
index 27266ce70..9d853f94d 100644
--- a/newlib/libc/stdio/refill.c
+++ b/newlib/libc/stdio/refill.c
@@ -102,9 +102,19 @@ _DEFUN(__srefill_r, (ptr, fp),
* flush all line buffered output files, per the ANSI C
* standard.
*/
-
if (fp->_flags & (__SLBF | __SNBF))
- _CAST_VOID _fwalk (_GLOBAL_REENT, lflush);
+ {
+ /* Ignore this file in _fwalk to avoid potential deadlock. */
+ short orig_flags = fp->_flags;
+ fp->_flags = 1;
+ _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->_r = fp->_read (ptr, fp->_cookie, (char *) fp->_p, fp->_bf._size);
#ifndef __CYGWIN__
diff --git a/newlib/libc/stdio/vfscanf.c b/newlib/libc/stdio/vfscanf.c
index fa4c598cf..42ebacd33 100644
--- a/newlib/libc/stdio/vfscanf.c
+++ b/newlib/libc/stdio/vfscanf.c
@@ -494,7 +494,6 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
# define GET_ARG(n, ap, type) (va_arg (ap, type))
#endif
- __sfp_lock_acquire ();
_flockfile (fp);
ORIENT (fp, -1);
@@ -795,7 +794,6 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
*/
case '\0': /* compat */
_funlockfile (fp);
- __sfp_lock_release ();
return EOF;
default: /* compat */
@@ -1596,13 +1594,11 @@ input_failure:
invalid format string), return EOF if no matches yet, else number
of matches made prior to failure. */
_funlockfile (fp);
- __sfp_lock_release ();
return nassigned && !(fp->_flags & __SERR) ? nassigned : EOF;
match_failure:
all_done:
/* Return number of matches, which can be 0 on match failure. */
_funlockfile (fp);
- __sfp_lock_release ();
return nassigned;
}
diff --git a/newlib/libc/stdio/vfwscanf.c b/newlib/libc/stdio/vfwscanf.c
index 56df93247..49ccf2f4b 100644
--- a/newlib/libc/stdio/vfwscanf.c
+++ b/newlib/libc/stdio/vfwscanf.c
@@ -434,7 +434,6 @@ _DEFUN(__SVFWSCANF_R, (rptr, fp, fmt0, ap),
# define GET_ARG(n, ap, type) (va_arg (ap, type))
#endif
- __sfp_lock_acquire ();
_flockfile (fp);
ORIENT (fp, 1);
@@ -714,7 +713,6 @@ _DEFUN(__SVFWSCANF_R, (rptr, fp, fmt0, ap),
*/
case L'\0': /* compat */
_funlockfile (fp);
- __sfp_lock_release ();
return EOF;
default: /* compat */
@@ -1443,13 +1441,11 @@ input_failure:
invalid format string), return EOF if no matches yet, else number
of matches made prior to failure. */
_funlockfile (fp);
- __sfp_lock_release ();
return nassigned && !(fp->_flags & __SERR) ? nassigned : EOF;
match_failure:
all_done:
/* Return number of matches, which can be 0 on match failure. */
_funlockfile (fp);
- __sfp_lock_release ();
return nassigned;
}
diff --git a/newlib/libc/stdio64/freopen64.c b/newlib/libc/stdio64/freopen64.c
index 866d8c943..1e2ec7827 100644
--- a/newlib/libc/stdio64/freopen64.c
+++ b/newlib/libc/stdio64/freopen64.c
@@ -97,7 +97,6 @@ _DEFUN (_freopen64_r, (ptr, file, mode, fp),
int flags, oflags;
int e = 0;
- __sfp_lock_acquire ();
CHECK_INIT (ptr, fp);
@@ -107,7 +106,6 @@ _DEFUN (_freopen64_r, (ptr, file, mode, fp),
{
_funlockfile(fp);
_fclose_r (ptr, fp);
- __sfp_lock_release ();
return NULL;
}
@@ -204,6 +202,7 @@ _DEFUN (_freopen64_r, (ptr, file, mode, fp),
if (f < 0)
{ /* did not get it after all */
+ __sfp_lock_acquire ();
fp->_flags = 0; /* set it free */
ptr->_errno = e; /* restore in case _close clobbered */
_funlockfile(fp);
@@ -231,7 +230,6 @@ _DEFUN (_freopen64_r, (ptr, file, mode, fp),
fp->_flags |= __SL64;
_funlockfile(fp);
- __sfp_lock_release ();
return fp;
}