diff options
author | deischen <deischen@FreeBSD.org> | 2001-02-11 22:06:43 +0000 |
---|---|---|
committer | deischen <deischen@FreeBSD.org> | 2001-02-11 22:06:43 +0000 |
commit | 1143b5e42a7816a7665798bcab7d5db4a37935b3 (patch) | |
tree | 3a588c82070b992d27ef67e1a69bcb90121e4ece | |
parent | d5657ce8b69e343a4dda07786bb158c464f9b4d6 (diff) | |
download | FreeBSD-src-1143b5e42a7816a7665798bcab7d5db4a37935b3.zip FreeBSD-src-1143b5e42a7816a7665798bcab7d5db4a37935b3.tar.gz |
libc MT-safety, part 2.
Add a lock to FILE. flockfile and friends are now implemented
(for the most part) in libc. flockfile_debug is implemented in
libc_r; I suppose it's about time to kill it but will do it in
a future commit.
Fix a potential deadlock in _fwalk in a threaded environment.
A file flag (__SIGN) was added to stdio.h that, when set, tells
_fwalk to ignore it in its walk. This seemed to be needed in
refill.c because each file needs to be locked when flushing.
Add a stub for pthread_self in libc. This is needed by flockfile
which is allowed by POSIX to be recursive.
Make fgetpos() error return value (-1) match man page.
Remove recursive calls to locked functions (stdio); I think I've
got them all, but I may have missed a couple.
A few K&R -> ANSI conversions along with removal of a few instances
of "register".
$Id$ -> $FreeBSD$ in libc/stdio/rget.c
Not objected to: -arch, a few months ago
-rw-r--r-- | lib/libc/gen/_pthread_stubs.c | 12 | ||||
-rw-r--r-- | lib/libc/include/namespace.h | 2 | ||||
-rw-r--r-- | lib/libc/include/un-namespace.h | 2 | ||||
-rw-r--r-- | lib/libc/stdio/_flock_stub.c | 150 | ||||
-rw-r--r-- | lib/libc/stdio/asprintf.c | 4 | ||||
-rw-r--r-- | lib/libc/stdio/fclose.c | 11 | ||||
-rw-r--r-- | lib/libc/stdio/feof.c | 20 | ||||
-rw-r--r-- | lib/libc/stdio/ferror.c | 20 | ||||
-rw-r--r-- | lib/libc/stdio/fflush.c | 17 | ||||
-rw-r--r-- | lib/libc/stdio/fgetc.c | 1 | ||||
-rw-r--r-- | lib/libc/stdio/fgetln.c | 30 | ||||
-rw-r--r-- | lib/libc/stdio/fgetpos.c | 19 | ||||
-rw-r--r-- | lib/libc/stdio/fileno.c | 11 | ||||
-rw-r--r-- | lib/libc/stdio/findfp.c | 6 | ||||
-rw-r--r-- | lib/libc/stdio/fopen.c | 1 | ||||
-rw-r--r-- | lib/libc/stdio/freopen.c | 4 | ||||
-rw-r--r-- | lib/libc/stdio/fwalk.c | 5 | ||||
-rw-r--r-- | lib/libc/stdio/getc.c | 5 | ||||
-rw-r--r-- | lib/libc/stdio/refill.c | 30 | ||||
-rw-r--r-- | lib/libc/stdio/rget.c | 9 | ||||
-rw-r--r-- | lib/libc/stdio/snprintf.c | 4 | ||||
-rw-r--r-- | lib/libc/stdio/sprintf.c | 2 |
22 files changed, 261 insertions, 104 deletions
diff --git a/lib/libc/gen/_pthread_stubs.c b/lib/libc/gen/_pthread_stubs.c index 87b0ad2..be6dab7 100644 --- a/lib/libc/gen/_pthread_stubs.c +++ b/lib/libc/gen/_pthread_stubs.c @@ -49,8 +49,14 @@ #pragma weak _pthread_mutexattr_destroy=_pthread_mutexattr_destroy_stub #pragma weak _pthread_mutexattr_settype=_pthread_mutexattr_settype_stub #pragma weak _pthread_once=_pthread_once_stub +#pragma weak _pthread_self=_pthread_self_stub #pragma weak _pthread_setspecific=_pthread_setspecific_stub +struct pthread { +}; + +static struct pthread main_thread; + void * _pthread_getspecific_stub(pthread_key_t key) @@ -124,6 +130,12 @@ _pthread_once_stub(pthread_once_t *once_control, void (*init_routine) (void)) return (0); } +pthread_t +_pthread_self_stub(void) +{ + return (&main_thread); +} + int _pthread_setspecific_stub(pthread_key_t key, const void *value) { diff --git a/lib/libc/include/namespace.h b/lib/libc/include/namespace.h index 95acce4..ddffa82 100644 --- a/lib/libc/include/namespace.h +++ b/lib/libc/include/namespace.h @@ -70,6 +70,7 @@ #define pthread_mutexattr_destroy _pthread_mutexattr_destroy #define pthread_mutexattr_settype _pthread_mutexattr_settype #define pthread_once _pthread_once +#define pthread_self _pthread_self #define pthread_setspecific _pthread_setspecific #define read _read #define readv _readv @@ -115,7 +116,6 @@ #define pthread_rwlock_wrlock _pthread_rwlock_wrlock #define pthread_rwlockattr_init _pthread_rwlockattr_init #define pthread_rwlockattr_destroy _pthread_rwlockattr_destroy -#define pthread_self _pthread_self #define sched_yield _sched_yield #define sendfile _sendfile #define shutdown _shutdown diff --git a/lib/libc/include/un-namespace.h b/lib/libc/include/un-namespace.h index 4d2e8bd..76ba625 100644 --- a/lib/libc/include/un-namespace.h +++ b/lib/libc/include/un-namespace.h @@ -65,6 +65,7 @@ #undef pthread_mutexattr_destroy #undef pthread_mutexattr_settype #undef pthread_once +#undef pthread_self #undef pthread_setspecific #undef read #undef readv @@ -102,7 +103,6 @@ #undef pthread_rwlock_wrlock #undef pthread_rwlockattr_init #undef pthread_rwlockattr_destroy -#undef pthread_self #undef sched_yield #undef sendfile #undef shutdown diff --git a/lib/libc/stdio/_flock_stub.c b/lib/libc/stdio/_flock_stub.c index 83a3e86..8bea66d 100644 --- a/lib/libc/stdio/_flock_stub.c +++ b/lib/libc/stdio/_flock_stub.c @@ -33,49 +33,155 @@ * */ +/* + * POSIX stdio FILE locking functions. These assume that the locking + * is only required at FILE structure level, not at file descriptor + * level too. + * + */ + +#include "namespace.h" #include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <pthread.h> +#include "un-namespace.h" + +/* + * Weak symbols for externally visible functions in this file: + */ +#pragma weak flockfile=_flockfile +#pragma weak _flockfile_debug=_flockfile_debug_stub +#pragma weak ftrylockfile=_ftrylockfile +#pragma weak funlockfile=_funlockfile + +static int init_lock(FILE *); /* - * Declare weak references in case the application is not linked - * with libpthread. + * The FILE lock structure. The FILE *fp is locked when the mutex + * is locked. */ -#pragma weak flockfile=_flockfile_stub -#pragma weak _flockfile=_flockfile_stub -#pragma weak _flockfile_debug=_flockfile_debug_stub -#pragma weak ftrylockfile=_ftrylockfile_stub -#pragma weak _ftrylockfile=_ftrylockfile_stub -#pragma weak funlockfile=_funlockfile_stub -#pragma weak _funlockfile=_funlockfile_stub +struct __file_lock { + pthread_mutex_t fl_mutex; + pthread_t fl_owner; /* current owner */ + int fl_count; /* recursive lock count */ +}; /* - * This function is a stub for the _flockfile function in libpthread. + * Allocate and initialize a file lock. */ +static int +init_lock(FILE *fp) +{ + struct __file_lock *p; + int ret; + + if ((p = malloc(sizeof(struct __file_lock))) == NULL) + ret = -1; + else { + p->fl_mutex = PTHREAD_MUTEX_INITIALIZER; + p->fl_owner = NULL; + p->fl_count = 0; + fp->_lock = p; + ret = 0; + } + return (ret); +} + void -_flockfile_stub(FILE *fp) +_flockfile(FILE *fp) { + pthread_t curthread = _pthread_self(); + + /* + * Check if this is a real file with a valid lock, creating + * the lock if needed: + */ + if ((fp->_file >= 0) && + ((fp->_lock != NULL) || (init_lock(fp) == 0))) { + if (fp->_lock->fl_owner == curthread) + fp->_lock->fl_count++; + else { + /* + * Make sure this mutex is treated as a private + * internal mutex: + */ + _pthread_mutex_lock(&fp->_lock->fl_mutex); + fp->_lock->fl_owner = curthread; + fp->_lock->fl_count = 1; + } + } } /* - * This function is a stub for the _flockfile_debug function in libpthread. + * This can be overriden by the threads library if it is linked in. */ void _flockfile_debug_stub(FILE *fp, char *fname, int lineno) { + _flockfile(fp); } -/* - * This function is a stub for the _ftrylockfile function in libpthread. - */ int -_ftrylockfile_stub(FILE *fp) +_ftrylockfile(FILE *fp) { - return(0); + pthread_t curthread = _pthread_self(); + int ret = 0; + + /* + * Check if this is a real file with a valid lock, creating + * the lock if needed: + */ + if ((fp->_file >= 0) && + ((fp->_lock != NULL) || (init_lock(fp) == 0))) { + if (fp->_lock->fl_owner == curthread) + fp->_lock->fl_count++; + /* + * Make sure this mutex is treated as a private + * internal mutex: + */ + else if (_pthread_mutex_trylock(&fp->_lock->fl_mutex) == 0) { + fp->_lock->fl_owner = curthread; + fp->_lock->fl_count = 1; + } + else + ret = -1; + } + else + ret = -1; + return (ret); } -/* - * This function is a stub for the _funlockfile function in libpthread. - */ -void -_funlockfile_stub(FILE *fp) +void +_funlockfile(FILE *fp) { + pthread_t curthread = _pthread_self(); + + /* + * Check if this is a real file with a valid lock owned + * by the current thread: + */ + if ((fp->_file >= 0) && (fp->_lock != NULL) && + (fp->_lock->fl_owner == curthread)) { + /* + * Check if this thread has locked the FILE + * more than once: + */ + if (fp->_lock->fl_count > 1) + /* + * Decrement the count of the number of + * times the running thread has locked this + * file: + */ + fp->_lock->fl_count--; + else { + /* + * The running thread will release the + * lock now: + */ + fp->_lock->fl_count = 0; + fp->_lock->fl_owner = NULL; + _pthread_mutex_unlock(&fp->_lock->fl_mutex); + } + } } diff --git a/lib/libc/stdio/asprintf.c b/lib/libc/stdio/asprintf.c index e125bfc..cf4fb3c 100644 --- a/lib/libc/stdio/asprintf.c +++ b/lib/libc/stdio/asprintf.c @@ -40,6 +40,8 @@ static char rcsid[] = "$FreeBSD$"; #include <varargs.h> #endif +#include "local.h" + int #if __STDC__ asprintf(char **str, char const *fmt, ...) @@ -68,7 +70,7 @@ asprintf(str, fmt, va_alist) return (-1); } f._bf._size = f._w = 127; /* Leave room for the NULL */ - ret = vfprintf(&f, fmt, ap); + ret = __vfprintf(&f, fmt, ap); /* Use unlocked __vfprintf */ *f._p = '\0'; va_end(ap); f._bf._base = reallocf(f._bf._base, f._bf._size + 1); diff --git a/lib/libc/stdio/fclose.c b/lib/libc/stdio/fclose.c index 0d6fd80..e70a2da 100644 --- a/lib/libc/stdio/fclose.c +++ b/lib/libc/stdio/fclose.c @@ -51,8 +51,7 @@ static const char rcsid[] = #include "local.h" int -fclose(fp) - FILE *fp; +fclose(FILE *fp) { int r; @@ -70,15 +69,9 @@ fclose(fp) FREEUB(fp); if (HASLB(fp)) FREELB(fp); - FUNLOCKFILE(fp); fp->_file = -1; fp->_r = fp->_w = 0; /* Mess up if reaccessed. */ -#if 0 - if (fp->_lock != NULL) { - _pthread_mutex_destroy((pthread_mutex_t *)&fp->_lock); - fp->_lock = NULL; - } -#endif fp->_flags = 0; /* Release this FILE for reuse. */ + FUNLOCKFILE(fp); return (r); } diff --git a/lib/libc/stdio/feof.c b/lib/libc/stdio/feof.c index 3581100..60cad53 100644 --- a/lib/libc/stdio/feof.c +++ b/lib/libc/stdio/feof.c @@ -42,16 +42,24 @@ static const char rcsid[] = "$FreeBSD$"; #endif /* LIBC_SCCS and not lint */ +#include "namespace.h" #include <stdio.h> +#include "un-namespace.h" +#include "libc_private.h" /* - * A subroutine version of the macro feof. + * feof has traditionally been a macro in <stdio.h>. That is no + * longer true because it needs to be thread-safe. + * + * #undef feof */ -#undef feof - int -feof(fp) - FILE *fp; +feof(FILE *fp) { - return (__sfeof(fp)); + int ret; + + FLOCKFILE(fp); + ret= __sfeof(fp); + FUNLOCKFILE(fp); + return (ret); } diff --git a/lib/libc/stdio/ferror.c b/lib/libc/stdio/ferror.c index 2311926..c4424c6 100644 --- a/lib/libc/stdio/ferror.c +++ b/lib/libc/stdio/ferror.c @@ -42,16 +42,24 @@ static const char rcsid[] = "$FreeBSD$"; #endif /* LIBC_SCCS and not lint */ +#include "namespace.h" #include <stdio.h> +#include "un-namespace.h" +#include "libc_private.h" /* - * A subroutine version of the macro ferror. + * ferror has traditionally been a macro in <stdio.h>. That is no + * longer true because it needs to be thread-safe. + * + * #undef ferror */ -#undef ferror - int -ferror(fp) - FILE *fp; +ferror(FILE *fp) { - return (__sferror(fp)); + int ret; + + FLOCKFILE(fp); + ret = __sferror(fp); + FUNLOCKFILE(fp); + return (ret); } diff --git a/lib/libc/stdio/fflush.c b/lib/libc/stdio/fflush.c index 09d346b..5c1eaa1 100644 --- a/lib/libc/stdio/fflush.c +++ b/lib/libc/stdio/fflush.c @@ -49,6 +49,8 @@ static const char rcsid[] = #include "libc_private.h" #include "local.h" +static int sflush_locked(FILE *); + /* * Flush a single file, or (if fp is NULL) all files. * MT-safe version @@ -59,7 +61,7 @@ fflush(FILE *fp) int retval; if (fp == NULL) - return (_fwalk(__sflush)); + return (_fwalk(sflush_locked)); FLOCKFILE(fp); if ((fp->_flags & (__SWR | __SRW)) == 0) { errno = EBADF; @@ -80,7 +82,7 @@ __fflush(FILE *fp) int retval; if (fp == NULL) - return (_fwalk(__sflush)); + return (_fwalk(sflush_locked)); if ((fp->_flags & (__SWR | __SRW)) == 0) { errno = EBADF; retval = EOF; @@ -120,3 +122,14 @@ __sflush(FILE *fp) } return (0); } + +static int +sflush_locked(FILE *fp) +{ + int ret; + + FLOCKFILE(fp); + ret = __sflush(fp); + FUNLOCKFILE(fp); + return (ret); +} diff --git a/lib/libc/stdio/fgetc.c b/lib/libc/stdio/fgetc.c index a367af3..684da00 100644 --- a/lib/libc/stdio/fgetc.c +++ b/lib/libc/stdio/fgetc.c @@ -46,6 +46,7 @@ static const char rcsid[] = #include <stdio.h> #include "un-namespace.h" #include "libc_private.h" +#include "local.h" int fgetc(fp) diff --git a/lib/libc/stdio/fgetln.c b/lib/libc/stdio/fgetln.c index 3987b0d..c607a9c 100644 --- a/lib/libc/stdio/fgetln.c +++ b/lib/libc/stdio/fgetln.c @@ -42,9 +42,12 @@ static const char rcsid[] = "$FreeBSD$"; #endif /* LIBC_SCCS and not lint */ +#include "namespace.h" #include <stdio.h> #include <stdlib.h> #include <string.h> +#include "un-namespace.h" +#include "libc_private.h" #include "local.h" /* @@ -54,10 +57,8 @@ static const char rcsid[] = * so we add 1 here. #endif */ -int -__slbexpand(fp, newsize) - FILE *fp; - size_t newsize; +static int +slbexpand(FILE *fp, size_t newsize) { void *p; @@ -81,23 +82,23 @@ __slbexpand(fp, newsize) * it if they wish. Thus, we set __SMOD in case the caller does. */ char * -fgetln(fp, lenp) - register FILE *fp; - size_t *lenp; +fgetln(FILE *fp, size_t *lenp) { - register unsigned char *p; - register size_t len; + unsigned char *p; + size_t len; size_t off; + FLOCKFILE(fp); /* make sure there is input */ if (fp->_r <= 0 && __srefill(fp)) { *lenp = 0; + FUNLOCKFILE(fp); return (NULL); } /* look for a newline in the input */ if ((p = memchr((void *)fp->_p, '\n', (size_t)fp->_r)) != NULL) { - register char *ret; + char *ret; /* * Found one. Flag buffer as modified to keep fseek from @@ -110,6 +111,7 @@ fgetln(fp, lenp) fp->_flags |= __SMOD; fp->_r -= len; fp->_p = p; + FUNLOCKFILE(fp); return (ret); } @@ -124,14 +126,14 @@ fgetln(fp, lenp) #define OPTIMISTIC 80 for (len = fp->_r, off = 0;; len += fp->_r) { - register size_t diff; + size_t diff; /* * Make sure there is room for more bytes. Copy data from * file buffer to line buffer, refill file and look for * newline. The loop stops only when we find a newline. */ - if (__slbexpand(fp, len + OPTIMISTIC)) + if (slbexpand(fp, len + OPTIMISTIC)) goto error; (void)memcpy((void *)(fp->_lb._base + off), (void *)fp->_p, len - off); @@ -145,7 +147,7 @@ fgetln(fp, lenp) p++; diff = p - fp->_p; len += diff; - if (__slbexpand(fp, len)) + if (slbexpand(fp, len)) goto error; (void)memcpy((void *)(fp->_lb._base + off), (void *)fp->_p, diff); @@ -157,9 +159,11 @@ fgetln(fp, lenp) #ifdef notdef fp->_lb._base[len] = 0; #endif + FUNLOCKFILE(fp); return ((char *)fp->_lb._base); error: *lenp = 0; /* ??? */ + FUNLOCKFILE(fp); return (NULL); /* ??? */ } diff --git a/lib/libc/stdio/fgetpos.c b/lib/libc/stdio/fgetpos.c index 239f6d1..51f14ef 100644 --- a/lib/libc/stdio/fgetpos.c +++ b/lib/libc/stdio/fgetpos.c @@ -42,19 +42,16 @@ static const char rcsid[] = "$FreeBSD$"; #endif /* LIBC_SCCS and not lint */ -#include "namespace.h" #include <stdio.h> -#include "un-namespace.h" -#include "libc_private.h" int -fgetpos(fp, pos) - FILE *fp; - fpos_t *pos; +fgetpos(FILE *fp, fpos_t *pos) { - int retval; - FLOCKFILE(fp); - retval = (*pos = ftello(fp)) == (fpos_t)-1; - FUNLOCKFILE(fp); - return(retval); + /* + * ftello is thread-safe; no need to lock fp. + */ + if ((*pos = ftello(fp)) == (fpos_t)-1) + return (-1); + else + return (0); } diff --git a/lib/libc/stdio/fileno.c b/lib/libc/stdio/fileno.c index 0c3a8dc..b8f500e 100644 --- a/lib/libc/stdio/fileno.c +++ b/lib/libc/stdio/fileno.c @@ -45,13 +45,14 @@ static const char rcsid[] = #include <stdio.h> /* - * A subroutine version of the macro fileno. + * fileno has traditionally been a macro in <stdio.h>. That is + * no longer true because it needs to be thread-safe. + * + * #undef fileno */ -#undef fileno - int -fileno(fp) - FILE *fp; +fileno(FILE *fp) { + /* ??? - Should probably use atomic_read. */ return (__sfileno(fp)); } diff --git a/lib/libc/stdio/findfp.c b/lib/libc/stdio/findfp.c index 30e8f90..f307e3e 100644 --- a/lib/libc/stdio/findfp.c +++ b/lib/libc/stdio/findfp.c @@ -82,7 +82,7 @@ static spinlock_t thread_lock = _SPINLOCK_INITIALIZER; #define THREAD_UNLOCK() if (__isthreaded) _SPINUNLOCK(&thread_lock) #if NOT_YET -#define SET_GLUE_PTR(ptr, val) atomic_set_ptr(&(ptr), (uintptr_t)(val)) +#define SET_GLUE_PTR(ptr, val) atomic_set_rel_ptr(&(ptr), (uintptr_t)(val)) #else #define SET_GLUE_PTR(ptr, val) ptr = val #endif @@ -150,7 +150,7 @@ found: fp->_ub._size = 0; fp->_lb._base = NULL; /* no line buffer */ fp->_lb._size = 0; - /* fp->_lock = NULL; */ +/* fp->_lock = NULL; */ /* once set always set (reused) */ return (fp); } @@ -203,7 +203,7 @@ _cleanup() void __sinit() { - /* make sure we clean up on exit */ + /* Make sure we clean up on exit. */ __cleanup = _cleanup; /* conservative */ __sdidinit = 1; } diff --git a/lib/libc/stdio/fopen.c b/lib/libc/stdio/fopen.c index 4ea2eb9..aca314c 100644 --- a/lib/libc/stdio/fopen.c +++ b/lib/libc/stdio/fopen.c @@ -74,7 +74,6 @@ fopen(file, mode) fp->_write = __swrite; fp->_seek = __sseek; fp->_close = __sclose; - /* fp->_lock = NULL; */ /* * When opening in append mode, even though we use O_APPEND, * we need to seek to the end so that ftell() gets the right diff --git a/lib/libc/stdio/freopen.c b/lib/libc/stdio/freopen.c index fd8612c..a434d5a 100644 --- a/lib/libc/stdio/freopen.c +++ b/lib/libc/stdio/freopen.c @@ -62,9 +62,9 @@ static const char rcsid[] = FILE * freopen(file, mode, fp) const char *file, *mode; - register FILE *fp; + FILE *fp; { - register int f; + int f; int flags, isopen, oflags, sverrno, wantfd; if ((flags = __sflags(mode, &oflags)) == 0) { diff --git a/lib/libc/stdio/fwalk.c b/lib/libc/stdio/fwalk.c index 17cb5ce..b943be4 100644 --- a/lib/libc/stdio/fwalk.c +++ b/lib/libc/stdio/fwalk.c @@ -61,10 +61,13 @@ _fwalk(function) * 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 = &__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->_flags & __SIGN) == 0)) ret |= (*function)(fp); return (ret); } diff --git a/lib/libc/stdio/getc.c b/lib/libc/stdio/getc.c index 1668407..cabc40c 100644 --- a/lib/libc/stdio/getc.c +++ b/lib/libc/stdio/getc.c @@ -46,11 +46,10 @@ static const char rcsid[] = #include <stdio.h> #include "un-namespace.h" #include "libc_private.h" +#include "local.h" -#undef getc int -getc(fp) - register FILE *fp; +getc(FILE *fp) { int retval; FLOCKFILE(fp); diff --git a/lib/libc/stdio/refill.c b/lib/libc/stdio/refill.c index 2db485bba..b597f97 100644 --- a/lib/libc/stdio/refill.c +++ b/lib/libc/stdio/refill.c @@ -42,22 +42,28 @@ static const char rcsid[] = "$FreeBSD$"; #endif /* LIBC_SCCS and not lint */ +#include "namespace.h" #include <errno.h> #include <stdio.h> #include <stdlib.h> +#include "un-namespace.h" +#include "libc_private.h" #include "local.h" static int lflush __P((FILE *)); static int -lflush(fp) - FILE *fp; +lflush(FILE *fp) { + int ret = 0; - if ((fp->_flags & (__SLBF|__SWR)) == (__SLBF|__SWR)) - return (__sflush(fp)); - return (0); + if ((fp->_flags & (__SLBF|__SWR)) == (__SLBF|__SWR)) { + FLOCKFILE(fp); + ret = __sflush(fp); + FUNLOCKFILE(fp); + } + return (ret); } /* @@ -65,10 +71,8 @@ lflush(fp) * Return EOF on eof or error, 0 otherwise. */ int -__srefill(fp) - register FILE *fp; +__srefill(FILE *fp) { - /* make sure stdio is set up */ if (!__sdidinit) __sinit(); @@ -119,8 +123,16 @@ __srefill(fp) * flush all line buffered output files, per the ANSI C * standard. */ - if (fp->_flags & (__SLBF|__SNBF)) + if (fp->_flags & (__SLBF|__SNBF)) { + /* Ignore this file in _fwalk to avoid potential deadlock. */ + fp->_flags |= __SIGN; (void) _fwalk(lflush); + fp->_flags &= ~__SIGN; + + /* Now flush this file without locking it. */ + if ((fp->_flags & (__SLBF|__SWR)) == (__SLBF|__SWR)) + __sflush(fp); + } fp->_p = fp->_bf._base; fp->_r = (*fp->_read)(fp->_cookie, (char *)fp->_p, fp->_bf._size); fp->_flags &= ~__SMOD; /* buffer contents are again pristine */ diff --git a/lib/libc/stdio/rget.c b/lib/libc/stdio/rget.c index 45d817d..4ec796f 100644 --- a/lib/libc/stdio/rget.c +++ b/lib/libc/stdio/rget.c @@ -39,22 +39,19 @@ static char sccsid[] = "@(#)rget.c 8.1 (Berkeley) 6/4/93"; #endif static const char rcsid[] = - "$Id"; + "$FreeBSD$"; #endif /* LIBC_SCCS and not lint */ #include <stdio.h> #include "local.h" -int -__srefill(FILE *); - /* * Handle getc() when the buffer ran out: * Refill, then return the first character * in the newly-filled buffer. */ -int __srget(fp) - register FILE *fp; +int +__srget(FILE *fp) { if (__srefill(fp) == 0) { fp->_r--; diff --git a/lib/libc/stdio/snprintf.c b/lib/libc/stdio/snprintf.c index bedf98d..fe21129 100644 --- a/lib/libc/stdio/snprintf.c +++ b/lib/libc/stdio/snprintf.c @@ -50,6 +50,8 @@ static const char rcsid[] = #include <varargs.h> #endif +#include "local.h" + #if __STDC__ int snprintf(char *str, size_t n, char const *fmt, ...) @@ -81,7 +83,7 @@ snprintf(str, n, fmt, va_alist) f._flags = __SWR | __SSTR; f._bf._base = f._p = (unsigned char *)str; f._bf._size = f._w = n; - ret = vfprintf(&f, fmt, ap); + ret = __vfprintf(&f, fmt, ap); if (on > 0) *f._p = '\0'; va_end(ap); diff --git a/lib/libc/stdio/sprintf.c b/lib/libc/stdio/sprintf.c index 10e73f0..a810096 100644 --- a/lib/libc/stdio/sprintf.c +++ b/lib/libc/stdio/sprintf.c @@ -74,7 +74,7 @@ sprintf(str, fmt, va_alist) #else va_start(ap); #endif - ret = vfprintf(&f, fmt, ap); + ret = __vfprintf(&f, fmt, ap); va_end(ap); *f._p = 0; return (ret); |