diff options
author | Nicholas Clark <nick@ccl4.org> | 2004-07-15 19:09:15 +0000 |
---|---|---|
committer | Nicholas Clark <nick@ccl4.org> | 2004-07-15 19:09:15 +0000 |
commit | d94006e83fb3a18ffb59fd5cb41bc7ab9d73a7f6 (patch) | |
tree | c908d5aec03806a2c5db585637dce0d669b1bd43 | |
parent | 7ada78df9739acac44e6c9a8f1e08c978571e2a0 (diff) | |
download | perl-d94006e83fb3a18ffb59fd5cb41bc7ab9d73a7f6.tar.gz |
threads.xs doesn't check the return value of the thread creation
call. D'oh! This gives SEGVs if the OS fails to create another thread.
Cause of problem located by Nigel Sandever
p4raw-id: //depot/perl@23120
-rwxr-xr-x | ext/threads/threads.pm | 5 | ||||
-rwxr-xr-x | ext/threads/threads.xs | 32 |
2 files changed, 30 insertions, 7 deletions
diff --git a/ext/threads/threads.pm b/ext/threads/threads.pm index a355f49fbe..dcd2aa015c 100755 --- a/ext/threads/threads.pm +++ b/ext/threads/threads.pm @@ -50,7 +50,7 @@ our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); our @EXPORT = qw( async ); -our $VERSION = '1.04'; +our $VERSION = '1.05'; # || 0 to ensure compatibility with previous versions @@ -139,7 +139,8 @@ it the other way around. This will create a new thread with the entry point function and give it LIST as parameters. It will return the corresponding threads -object. The new() method is an alias for create(). +object, or C<undef> if thread creation failed. The new() method is an +alias for create(). =item $thread->join diff --git a/ext/threads/threads.xs b/ext/threads/threads.xs index e52143d587..4148fb0ac8 100755 --- a/ext/threads/threads.xs +++ b/ext/threads/threads.xs @@ -381,6 +381,10 @@ Perl_ithread_create(pTHX_ SV *obj, char* classname, SV* init_function, SV* param SV** tmps_tmp = PL_tmps_stack; I32 tmps_ix = PL_tmps_ix; +#ifndef WIN32 + int failure; + const char* panic = NULL; +#endif MUTEX_LOCK(&create_destruct_mutex); @@ -480,10 +484,8 @@ Perl_ithread_create(pTHX_ SV *obj, char* classname, SV* init_function, SV* param /* Start the thread */ #ifdef WIN32 - thread->handle = CreateThread(NULL, 0, Perl_ithread_run, (LPVOID)thread, 0, &thread->thr); - #else { static pthread_attr_t attr; @@ -498,20 +500,40 @@ Perl_ithread_create(pTHX_ SV *obj, char* classname, SV* init_function, SV* param # endif # ifdef THREAD_CREATE_NEEDS_STACK if(pthread_attr_setstacksize(&attr, THREAD_CREATE_NEEDS_STACK)) - Perl_croak(aTHX_ "panic: pthread_attr_setstacksize failed"); + panic = "panic: pthread_attr_setstacksize failed"; # endif #ifdef OLD_PTHREADS_API - pthread_create( &thread->thr, attr, Perl_ithread_run, (void *)thread); + failure + = panic ? 1 : pthread_create( &thread->thr, attr, + Perl_ithread_run, (void *)thread); #else # if defined(HAS_PTHREAD_ATTR_SETSCOPE) && defined(PTHREAD_SCOPE_SYSTEM) pthread_attr_setscope( &attr, PTHREAD_SCOPE_SYSTEM ); # endif - pthread_create( &thread->thr, &attr, Perl_ithread_run, (void *)thread); + failure + = panic ? 1 : pthread_create( &thread->thr, &attr, + Perl_ithread_run, (void *)thread); #endif } #endif known_threads++; + if ( +#ifdef WIN32 + thread->handle == NULL +#else + failure +#endif + ) { + MUTEX_UNLOCK(&create_destruct_mutex); + sv_2mortal(params); + Perl_ithread_destruct(aTHX_ thread, "create failed"); +#ifndef WIN32 + if (panic) + Perl_croak(aTHX_ panic); +#endif + return &PL_sv_undef; + } active_threads++; MUTEX_UNLOCK(&create_destruct_mutex); sv_2mortal(params); |