diff options
author | Gurusamy Sarathy <gsar@cpan.org> | 2001-07-05 00:42:49 +0000 |
---|---|---|
committer | Gurusamy Sarathy <gsar@cpan.org> | 2001-07-05 00:42:49 +0000 |
commit | 50dd6e574ff39b609595ddb16b2fe9f625a26f8c (patch) | |
tree | 75623d7252059f79bb9271a8ea59619aaee0be4f | |
parent | d3a7fa0a676f35fac595b7197c9c94e498857827 (diff) | |
download | perl-50dd6e574ff39b609595ddb16b2fe9f625a26f8c.tar.gz |
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()
p4raw-id: //depot/perl@11151
-rw-r--r-- | perl.c | 29 | ||||
-rw-r--r-- | thread.h | 9 | ||||
-rw-r--r-- | win32/win32thread.h | 2 |
3 files changed, 40 insertions, 0 deletions
@@ -58,6 +58,32 @@ static I32 read_e_script(pTHXo_ int idx, SV *buf_sv, int maxlen); } 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 @@ static I32 read_e_script(pTHXo_ int idx, SV *buf_sv, int maxlen); 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); \ @@ -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 @@ typedef struct condpair { #ifndef INIT_THREADS # define INIT_THREADS NOOP #endif + +#ifndef PTHREAD_ATFORK +# define PTHREAD_ATFORK(prepare,parent,child) NOOP +#endif diff --git a/win32/win32thread.h b/win32/win32thread.h index 1f8840c0c0..7105eca2e5 100644 --- a/win32/win32thread.h +++ b/win32/win32thread.h @@ -180,6 +180,8 @@ END_EXTERN_C 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 { \ |