diff options
author | Thomas Pfaff <tpfaff@gmx.net> | 2003-01-09 20:57:54 +0000 |
---|---|---|
committer | Thomas Pfaff <tpfaff@gmx.net> | 2003-01-09 20:57:54 +0000 |
commit | 09cbb9d6b737a7acf228731945b599c13e6c5d92 (patch) | |
tree | 803e44b22dc2551be42d8a2fde3c8d1358689af1 /winsup/cygwin/thread.cc | |
parent | 72fcbc3ee690a028128274d2bd0ad694961b5e5f (diff) | |
download | cygnal-09cbb9d6b737a7acf228731945b599c13e6c5d92.tar.gz cygnal-09cbb9d6b737a7acf228731945b599c13e6c5d92.tar.bz2 cygnal-09cbb9d6b737a7acf228731945b599c13e6c5d92.zip |
Apply pthread_cancel_patch
Diffstat (limited to 'winsup/cygwin/thread.cc')
-rw-r--r-- | winsup/cygwin/thread.cc | 70 |
1 files changed, 57 insertions, 13 deletions
diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc index 2aac4b3b3..dee6eb05a 100644 --- a/winsup/cygwin/thread.cc +++ b/winsup/cygwin/thread.cc @@ -471,7 +471,7 @@ pwrite () read () readv () select () -sem_wait () +*sem_wait () sigpause () sigsuspend () sigtimedwait () @@ -632,6 +632,28 @@ pthread::static_cancel_self (void) } +DWORD pthread::cancelable_wait (HANDLE object, DWORD timeout, const bool do_cancel) +{ + DWORD res; + HANDLE wait_objects[2]; + pthread_t thread = self (); + + if (!isGoodObject (&thread) || thread->cancelstate == PTHREAD_CANCEL_DISABLE) + return WaitForSingleObject (object, timeout); + + // Do not change the wait order + // The object must have higher priority than the cancel event, + // because WaitForMultipleObjects will return the smallest index + // if both objects are signaled + wait_objects[0] = object; + wait_objects[1] = thread->cancel_event; + + res = WaitForMultipleObjects (2, wait_objects, FALSE, timeout); + if (do_cancel && res == WAIT_CANCELED) + pthread::static_cancel_self (); + return res; +} + int pthread::setcancelstate (int state, int *oldstate) { @@ -1390,8 +1412,15 @@ semaphore::TryWait () void semaphore::Wait () { - WaitForSingleObject (win32_obj_id, INFINITE); - currentvalue--; + switch (pthread::cancelable_wait (win32_obj_id, INFINITE)) + { + case WAIT_OBJECT_0: + currentvalue--; + break; + default: + debug_printf ("cancelable_wait failed. %E"); + return; + } } void @@ -1850,14 +1879,15 @@ pthread::join (pthread_t *thread, void **return_val) { pthread_t joiner = self (); - if (!isGoodObject (&joiner)) - return EINVAL; + joiner->testcancel (); // Initialize return val with NULL if (return_val) *return_val = NULL; - /* FIXME: wait on the thread cancellation event as well - we are a cancellation point*/ + if (!isGoodObject (&joiner)) + return EINVAL; + if (!isGoodObject (thread)) return ESRCH; @@ -1876,14 +1906,26 @@ pthread::join (pthread_t *thread, void **return_val) (*thread)->joiner = joiner; (*thread)->attr.joinable = PTHREAD_CREATE_DETACHED; (*thread)->mutex.UnLock (); - WaitForSingleObject ((*thread)->win32_obj_id, INFINITE); - if (return_val) - *return_val = (*thread)->return_ptr; - // cleanup - delete (*thread); - } /* End if */ - pthread_testcancel (); + switch (cancelable_wait ((*thread)->win32_obj_id, INFINITE, false)) + { + case WAIT_OBJECT_0: + if (return_val) + *return_val = (*thread)->return_ptr; + delete (*thread); + break; + case WAIT_CANCELED: + // set joined thread back to joinable since we got canceled + (*thread)->joiner = NULL; + (*thread)->attr.joinable = PTHREAD_CREATE_JOINABLE; + joiner->cancel_self (); + // never reached + break; + default: + // should never happen + return EINVAL; + } + } return 0; } @@ -2629,6 +2671,8 @@ semaphore::destroy (sem_t *sem) int semaphore::wait (sem_t *sem) { + pthread_testcancel (); + if (!isGoodObject (sem)) { set_errno (EINVAL); |