diff options
Diffstat (limited to 'libpthread/linuxthreads.old/join.c')
-rw-r--r-- | libpthread/linuxthreads.old/join.c | 21 |
1 files changed, 15 insertions, 6 deletions
diff --git a/libpthread/linuxthreads.old/join.c b/libpthread/linuxthreads.old/join.c index 6a8a9d982..4bdc77a25 100644 --- a/libpthread/linuxthreads.old/join.c +++ b/libpthread/linuxthreads.old/join.c @@ -27,16 +27,25 @@ void pthread_exit(void * retval) { + __pthread_do_exit (retval, CURRENT_STACK_FRAME); +} + +void __pthread_do_exit(void *retval, char *currentframe) +{ pthread_descr self = thread_self(); pthread_descr joining; struct pthread_request request; PDEBUG("self=%p, pid=%d\n", self, self->p_pid); - /* Reset the cancellation flag to avoid looping if the cleanup handlers - contain cancellation points */ - THREAD_SETMEM(self, p_canceled, 0); + /* obey POSIX behavior and prevent cancellation functions from + * being called more than once. + * http://sourceware.org/ml/libc-ports/2006-10/msg00043.html + */ + THREAD_SETMEM(self, p_cancelstate, PTHREAD_CANCEL_DISABLE); + THREAD_SETMEM(self, p_canceltype, PTHREAD_CANCEL_DEFERRED); + /* Call cleanup functions and destroy the thread-specific data */ - __pthread_perform_cleanup(); + __pthread_perform_cleanup(currentframe); __pthread_destroy_specifics(); /* Store return value */ __pthread_lock(THREAD_GETMEM(self, p_lock), self); @@ -150,7 +159,7 @@ int pthread_join(pthread_t thread_id, void ** thread_return) if (already_canceled) { __pthread_set_own_extricate_if(self, 0); - pthread_exit(PTHREAD_CANCELED); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); } PDEBUG("before suspend\n"); @@ -163,7 +172,7 @@ int pthread_join(pthread_t thread_id, void ** thread_return) if (THREAD_GETMEM(self, p_woken_by_cancel) && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) { THREAD_SETMEM(self, p_woken_by_cancel, 0); - pthread_exit(PTHREAD_CANCELED); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); } __pthread_lock(&handle->h_lock, self); } |