summaryrefslogtreecommitdiff
path: root/lib/libc/stdio/flockfile.c
diff options
context:
space:
mode:
authornathanw <nathanw@NetBSD.org>2003-07-18 21:50:41 +0000
committernathanw <nathanw@NetBSD.org>2003-07-18 21:50:41 +0000
commitad09d62fccedf9d8cbddb98aaa2b917136d9802d (patch)
treef29c67f126ad1905ef08595debce2692e95cf7cb /lib/libc/stdio/flockfile.c
parentb5665a9b84a4aa2e1bfffd4c9322e9a3fe2445f4 (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.c61
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;