diff options
| author | nathanw <nathanw@NetBSD.org> | 2003-07-18 21:50:41 +0000 |
|---|---|---|
| committer | nathanw <nathanw@NetBSD.org> | 2003-07-18 21:50:41 +0000 |
| commit | ad09d62fccedf9d8cbddb98aaa2b917136d9802d (patch) | |
| tree | f29c67f126ad1905ef08595debce2692e95cf7cb /lib/libc/stdio | |
| parent | b5665a9b84a4aa2e1bfffd4c9322e9a3fe2445f4 (diff) | |
Move guts of flockfile()/funlockfile() to __flockfile_internal(), which
takes an additional argument indicating whether this is an internal caller
taking the lock or an external (application) caller. When making an internal
lock, save the current thread cancellation state and disable cancellation
until the matching unlock. This should prevent canccelled threads from exiting
inside of stdio while holding a file lock and potentially leaving other
parts of the FILE structure in an inconsistent state.
Diffstat (limited to 'lib/libc/stdio')
| -rw-r--r-- | lib/libc/stdio/flockfile.c | 61 | ||||
| -rw-r--r-- | lib/libc/stdio/local.h | 4 |
2 files changed, 47 insertions, 18 deletions
diff --git a/lib/libc/stdio/flockfile.c b/lib/libc/stdio/flockfile.c index 7fba26b2d0a..efa420f93e0 100644 --- a/lib/libc/stdio/flockfile.c +++ b/lib/libc/stdio/flockfile.c @@ -1,4 +1,4 @@ -/* $NetBSD: flockfile.c,v 1.4 2003/02/01 03:25:00 nathanw Exp $ */ +/* $NetBSD: flockfile.c,v 1.5 2003/07/18 21:50:41 nathanw Exp $ */ /*- * Copyright (c) 2002 The NetBSD Foundation, Inc. @@ -38,7 +38,7 @@ #include <sys/cdefs.h> #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: flockfile.c,v 1.4 2003/02/01 03:25:00 nathanw Exp $"); +__RCSID("$NetBSD: flockfile.c,v 1.5 2003/07/18 21:50:41 nathanw Exp $"); #endif /* LIBC_SCCS and not lint */ #include "namespace.h" @@ -68,21 +68,7 @@ void flockfile(FILE *fp) { - if (__isthreaded == 0) - return; - - mutex_lock(&_LOCK(fp)); - - if (_LOCKOWNER(fp) == thr_self()) { - _LOCKCOUNT(fp)++; - } else { - while (_LOCKOWNER(fp) != NULL) - cond_wait(&_LOCKCOND(fp), &_LOCK(fp)); - _LOCKOWNER(fp) = thr_self(); - _LOCKCOUNT(fp) = 1; - } - - mutex_unlock(&_LOCK(fp)); + __flockfile_internal(fp, 0); } int @@ -113,11 +99,52 @@ void funlockfile(FILE *fp) { + __funlockfile_internal(fp, 0); +} + +void +__flockfile_internal(FILE *fp, int internal) +{ + if (__isthreaded == 0) return; mutex_lock(&_LOCK(fp)); + if (_LOCKOWNER(fp) == thr_self()) { + _LOCKCOUNT(fp)++; + if (internal) { + if (_LOCKINTERNAL(fp) == 0) + /* stash cancellation state and disable */ + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, + &_LOCKCANCELSTATE(fp)); + _LOCKINTERNAL(fp)++; + } + } else { + while (_LOCKOWNER(fp) != NULL) + cond_wait(&_LOCKCOND(fp), &_LOCK(fp)); + _LOCKOWNER(fp) = thr_self(); + _LOCKCOUNT(fp) = 1; + } + + mutex_unlock(&_LOCK(fp)); +} + +void +__funlockfile_internal(FILE *fp, int internal) +{ + + if (__isthreaded == 0) + return; + + mutex_lock(&_LOCK(fp)); + + if (internal) { + _LOCKINTERNAL(fp)--; + if (_LOCKINTERNAL(fp) == 0) + pthread_setcancelstate(_LOCKCANCELSTATE(fp), NULL); + } + _LOCKCOUNT(fp)--; if (_LOCKCOUNT(fp) == 0) { _LOCKOWNER(fp) = NULL; diff --git a/lib/libc/stdio/local.h b/lib/libc/stdio/local.h index 64e6d2e3916..41c3ab9274c 100644 --- a/lib/libc/stdio/local.h +++ b/lib/libc/stdio/local.h @@ -1,4 +1,4 @@ -/* $NetBSD: local.h,v 1.15 2003/03/07 07:11:38 tshiozak Exp $ */ +/* $NetBSD: local.h,v 1.16 2003/07/18 21:50:41 nathanw Exp $ */ /*- * Copyright (c) 1990, 1993 @@ -102,3 +102,5 @@ extern wint_t __fputwc_unlock __P((wchar_t, FILE *)); (fp)->_lb._base = NULL; \ } +extern void __flockfile_internal __P((FILE *, int)); +extern void __funlockfile_internal __P((FILE *, int)); |
