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()
p4raw-id: //depot/perl@11151
} 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) { \
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); \
} 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))
#ifndef INIT_THREADS
# define INIT_THREADS NOOP
#endif
+
+#ifndef PTHREAD_ATFORK
+# define PTHREAD_ATFORK(prepare,parent,child) NOOP
+#endif
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 { \