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/flockfile.c | |
| 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/flockfile.c')
| -rw-r--r-- | lib/libc/stdio/flockfile.c | 61 |
1 files changed, 44 insertions, 17 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; |
