Change 11151 by gsar@latte-gsar on 2001/07/05 00:42:49

        perl built with USE_ITHREADS can deadlock during fork() or backticks
        since it doesn't ensure threads other than the one calling fork()
        aren't holding any locks; the fix is to use pthread_atfork() to
        hold global locks
        
        building perl with -Dusemymalloc exacerbates the problem since
        Perl_malloc() holds a mutex, and perl's exec() calls New()
        
        XXX the code in win32thread.h may be needed on platforms that have
        no pthread_atfork()

Affected files ...

... //depot/perl/perl.c#342 edit
... //depot/perl/thread.h#73 edit
... //depot/perl/win32/win32thread.h#21 edit

Differences ...

==== //depot/perl/perl.c#342 (text) ====
Index: perl/perl.c
--- perl/perl.c.~1~     Wed Jul  4 18:45:05 2001
+++ perl/perl.c Wed Jul  4 18:45:05 2001
@@ -58,6 +58,32 @@
     } STMT_END
 #else
 #  if defined(USE_ITHREADS)
+
+static void S_atfork_lock(void);
+static void S_atfork_unlock(void);
+
+/* this is called in parent before the fork() */
+static void
+S_atfork_lock(void)
+{
+    /* locks must be held in locking order (if any) */
+#ifdef MYMALLOC
+    MUTEX_LOCK(&PL_malloc_mutex);
+#endif
+    OP_REFCNT_LOCK;
+}
+
+/* this is called in both parent and child after the fork() */
+static void
+S_atfork_unlock(void)
+{
+    /* locks must be released in same order as in S_atfork_lock() */
+#ifdef MYMALLOC
+    MUTEX_UNLOCK(&PL_malloc_mutex);
+#endif
+    OP_REFCNT_UNLOCK;
+}
+
 #  define INIT_TLS_AND_INTERP \
     STMT_START {                               \
        if (!PL_curinterp) {                    \
@@ -66,6 +92,9 @@
            ALLOC_THREAD_KEY;                   \
            PERL_SET_THX(my_perl);              \
            OP_REFCNT_INIT;                     \
+           PTHREAD_ATFORK(S_atfork_lock,       \
+                          S_atfork_unlock,     \
+                          S_atfork_unlock);    \
        }                                       \
        else {                                  \
            PERL_SET_THX(my_perl);              \

==== //depot/perl/thread.h#73 (text) ====
Index: perl/thread.h
--- perl/thread.h.~1~   Wed Jul  4 18:45:05 2001
+++ perl/thread.h       Wed Jul  4 18:45:05 2001
@@ -302,6 +302,11 @@
     } STMT_END
 #endif
 
+#ifndef PTHREAD_ATFORK
+#  define PTHREAD_ATFORK(prepare,parent,child)                 \
+    pthread_atfork(prepare,parent,child)
+#endif
+
 #ifndef THREAD_RET_TYPE
 #  define THREAD_RET_TYPE      void *
 #  define THREAD_RET_CAST(p)   ((void *)(p))
@@ -456,3 +461,7 @@
 #ifndef INIT_THREADS
 #  define INIT_THREADS NOOP
 #endif
+
+#ifndef PTHREAD_ATFORK
+#  define PTHREAD_ATFORK(prepare,parent,child) NOOP
+#endif

==== //depot/perl/win32/win32thread.h#21 (text) ====
Index: perl/win32/win32thread.h
--- perl/win32/win32thread.h.~1~        Wed Jul  4 18:45:05 2001
+++ perl/win32/win32thread.h    Wed Jul  4 18:45:05 2001
@@ -180,6 +180,8 @@
        TlsFree(PL_thr_key);                                            \
     } STMT_END
 
+#define PTHREAD_ATFORK(prepare,parent,child)   NOOP
+
 #if defined(USE_RTL_THREAD_API) && !defined(_MSC_VER)
 #define JOIN(t, avp)                                                   \
     STMT_START {                                                       \
End of Patch.

Reply via email to