This is the mail archive of the libc-alpha@sourceware.cygnus.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

LinuxThreads bugfix---fork() vs. pthread_once.


I have discovered a defect related to the handling of the global mutex
``once_masterlock'' when one of the threads does a fork. As in, it's not done.
As a result, a deadlock will occur in the child process if the fork happens
while the lock is held, and the child executes pthread_once.

This is the patch. Basically, I have added a function which resets the
pthread once condition variable and mutex in the child process and hooked
it into the fork() override function.

Index: internals.h
===================================================================
RCS file: /cvs/glibc/libc/linuxthreads/internals.h,v
retrieving revision 1.15.2.9
diff -u -r1.15.2.9 internals.h
--- internals.h	2000/01/12 11:57:16	1.15.2.9
+++ internals.h	2000/03/22 16:38:25
@@ -387,6 +387,7 @@
 int __pthread_manager_event(void *reqfd);
 void __pthread_manager_sighandler(int sig);
 void __pthread_reset_main_thread(void);
+void __pthread_reset_pthread_once(void);
 void __fresetlockfiles(void);
 void __pthread_manager_adjust_prio(int thread_prio);
 void __pthread_set_own_extricate_if(pthread_descr self, pthread_extricate_if *peif);
Index: mutex.c
===================================================================
RCS file: /cvs/glibc/libc/linuxthreads/mutex.c,v
retrieving revision 1.9.2.2
diff -u -r1.9.2.2 mutex.c
--- mutex.c	2000/03/16 21:29:42	1.9.2.2
+++ mutex.c	2000/03/22 16:38:25
@@ -223,3 +223,15 @@
   return 0;
 }
 strong_alias (__pthread_once, pthread_once)
+
+/*
+ * This is called in the child process after a fork to make
+ * sure that the global mutex pthread_once is not held,
+ * and that the condition variable is reset to an initial state.
+ */
+
+void __pthread_reset_pthread_once(void)
+{
+  pthread_mutex_init(&once_masterlock, NULL);
+  pthread_cond_init(&once_finished, NULL);
+}
Index: ptfork.c
===================================================================
RCS file: /cvs/glibc/libc/linuxthreads/ptfork.c,v
retrieving revision 1.3.2.2
diff -u -r1.3.2.2 ptfork.c
--- ptfork.c	1999/09/05 17:36:30	1.3.2.2
+++ ptfork.c	2000/03/22 16:38:25
@@ -89,6 +89,7 @@
   pid = __libc_fork();
   if (pid == 0) {
     __pthread_reset_main_thread();
+    __pthread_reset_pthread_once();
     __fresetlockfiles();
     pthread_call_handlers(child);
   } else {


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]