diff -urp src.old/winsup/cygwin/thread.cc src/winsup/cygwin/thread.cc --- src.old/winsup/cygwin/thread.cc Thu Apr 25 10:11:30 2002 +++ src/winsup/cygwin/thread.cc Thu Apr 25 10:49:22 2002 @@ -346,7 +346,8 @@ MTinterface::fixup_after_fork (void) } pthread::pthread ():verifyable_object (PTHREAD_MAGIC), win32_obj_id (0), - cancelstate (0), canceltype (0), cleanup_handlers(NULL), joiner(NULL) + cancelstate (0), canceltype (0), mutex(NULL), + cleanup_handlers(NULL), joiner(NULL) { } @@ -354,6 +355,7 @@ pthread::~pthread () { if (win32_obj_id) CloseHandle (win32_obj_id); + __pthread_mutex_destroy(&mutex); } @@ -361,6 +363,8 @@ void pthread::create (void *(*func) (void *), pthread_attr *newattr, void *threadarg) { + int temperr; + /*already running ? */ if (win32_obj_id) return; @@ -375,6 +379,14 @@ pthread::create (void *(*func) (void *), function = func; arg = threadarg; + if ((temperr = __pthread_mutex_init (&mutex, NULL))) + { + system_printf ("couldn't init mutex, this %p errno %d", this, temperr); + /*we need the mutex for correct behaviour */ + magic = 0; + return; + } + win32_obj_id = ::CreateThread (&sec_none_nih, attr.stacksize, (LPTHREAD_START_ROUTINE) thread_init_wrapper, this, CREATE_SUSPENDED, &thread_id); @@ -908,9 +920,11 @@ thread_init_wrapper (void *_arg) /*the OS doesn't check this for <= 64 Tls entries (pre win2k) */ TlsSetValue (MT_INTERFACE->thread_self_dwTlsIndex, thread); + __pthread_mutex_lock(&thread->mutex); // if thread is detached force cleanup on exit if (thread->attr.joinable == PTHREAD_CREATE_DETACHED && thread->joiner == NULL) thread->joiner = __pthread_self(); + __pthread_mutex_unlock(&thread->mutex); #ifdef _CYG_THREAD_FAILSAFE if (_REENT == _impure_ptr) @@ -1225,8 +1239,13 @@ __pthread_cleanup_push (__pthread_cleanu { pthread_t thread = __pthread_self (); + // cleanup_push is not async cancel safe + __pthread_mutex_lock(&thread->mutex); + handler->next = thread->cleanup_handlers; thread->cleanup_handlers = handler; + + __pthread_mutex_unlock(&thread->mutex); } void @@ -1537,11 +1556,15 @@ __pthread_exit (void *value_ptr) MT_INTERFACE->destructors.IterateNull (); - // cleanup if thread is in detached state and not joined + __pthread_mutex_lock(&thread->mutex); if( __pthread_equal(&thread->joiner, &thread ) ) + // cleanup if thread is in detached state and not joined delete thread; else - thread->return_ptr = value_ptr; + { + __pthread_mutex_unlock(&thread->mutex); + thread->return_ptr = value_ptr; + } if (InterlockedDecrement (&MT_INTERFACE->threadcount) == 0) exit (0); @@ -1558,24 +1581,27 @@ __pthread_join (pthread_t *thread, void if (verifyable_object_isvalid (thread, PTHREAD_MAGIC) != VALID_OBJECT) return ESRCH; - if ((*thread)->attr.joinable == PTHREAD_CREATE_DETACHED) + if( __pthread_equal(thread, &joiner ) ) { if (return_val) *return_val = NULL; - return EINVAL; + return EDEADLK; } - else if( __pthread_equal(thread, &joiner ) ) + __pthread_mutex_lock(&(*thread)->mutex); + if ((*thread)->attr.joinable == PTHREAD_CREATE_DETACHED) { + __pthread_mutex_unlock(&(*thread)->mutex); if (return_val) *return_val = NULL; - return EDEADLK; + return EINVAL; } else { (*thread)->joiner = joiner; (*thread)->attr.joinable = PTHREAD_CREATE_DETACHED; + __pthread_mutex_unlock(&(*thread)->mutex); WaitForSingleObject ((*thread)->win32_obj_id, INFINITE); if (return_val) *return_val = (*thread)->return_ptr; @@ -1594,14 +1620,23 @@ __pthread_detach (pthread_t *thread) if (verifyable_object_isvalid (thread, PTHREAD_MAGIC) != VALID_OBJECT) return ESRCH; + __pthread_mutex_lock(&(*thread)->mutex); if ((*thread)->attr.joinable == PTHREAD_CREATE_DETACHED) { + __pthread_mutex_unlock(&(*thread)->mutex); return EINVAL; } - // force cleanup on exit - (*thread)->joiner = *thread; - (*thread)->attr.joinable = PTHREAD_CREATE_DETACHED; + // check if thread is still alive + if( WAIT_TIMEOUT == WaitForSingleObject ((*thread)->win32_obj_id, 0) ) + { + (*thread)->joiner = *thread; + (*thread)->attr.joinable = PTHREAD_CREATE_DETACHED; + __pthread_mutex_unlock(&(*thread)->mutex); + } + else + // thread has already terminated + delete (*thread); return 0; } diff -urp src.old/winsup/cygwin/thread.h src/winsup/cygwin/thread.h --- src.old/winsup/cygwin/thread.h Thu Apr 25 10:11:30 2002 +++ src/winsup/cygwin/thread.h Thu Apr 25 09:15:17 2002 @@ -239,6 +239,7 @@ public: void *return_ptr; bool suspended; int cancelstate, canceltype; + pthread_mutex *mutex; __pthread_cleanup_handler *cleanup_handlers; pthread_t joiner; // int joinable;