diff options
author | Christopher Faylor <me@cgf.cx> | 2012-12-21 22:52:00 +0400 |
---|---|---|
committer | Christopher Faylor <me@cgf.cx> | 2012-12-21 22:52:00 +0400 |
commit | 614aff88a0cf6c0ec5ec5ba063b003549dedc9db (patch) | |
tree | f750a571791d6d564bc7a5a252e2f2b78f22ec74 /winsup/cygwin/sigproc.cc | |
parent | dfbb1d0383420c383b8f0bc3149d4b76fa51b398 (diff) |
* DevNotes: Add entry cgf-000017.
* _cygtls.cc (_cygtls::call2): Use new exit_thread function in place of
ExitThread.
* miscfuncs.cc (thread_wrapper): Ditto.
* thread.cc (pthread::exit): Ditto.
(pthread_mutex::unlock): Set tid to NULL rather than 0.
(pthread_spinlock::unlock): Ditto.
* pinfo.cc (commune_process): Actually call lock_process constructor.
* sigproc.cc (exit_thread): New function.
(wait_sig): Handle __SIGTHREADEXIT case. Don't just block rather than
returning from this function.
* sigproc.h (__SIGTHREADEXIT): New enum.
(exit_thread): Declare.
* sync.cc (muto::release): Accept a tls command-line argument.
* sync.h (muto::release): Accept a tls command-line parameter. Default to
&_my_tls.
Diffstat (limited to 'winsup/cygwin/sigproc.cc')
-rw-r--r-- | winsup/cygwin/sigproc.cc | 49 |
1 files changed, 48 insertions, 1 deletions
diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc index a08a55ed3..be89d8685 100644 --- a/winsup/cygwin/sigproc.cc +++ b/winsup/cygwin/sigproc.cc @@ -553,6 +553,33 @@ sigproc_terminate (exit_states es) } } +/* Exit the current thread very carefully. + See cgf-000017 in DevNotes for more details on why this is + necessary. */ +void +exit_thread (DWORD res) +{ + HANDLE h; + + if (!DuplicateHandle (GetCurrentProcess (), GetCurrentThread (), + GetCurrentProcess (), &h, + 0, FALSE, DUPLICATE_SAME_ACCESS)) + { +#ifdef DEBUGGING + system_printf ("couldn't duplicate the current thread, %E"); +#endif + ExitThread (res); + } + ProtectHandle1 (h, exit_thread); + siginfo_t si = {__SIGTHREADEXIT, SI_KERNEL}; + si.si_value.sival_ptr = h; + /* Tell wait_sig to wait for this thread to exit. It can then release + the lock below and close the above-opened handle. */ + sig_send (myself_nowait, si, &_my_tls); + lock_process for_now; + ExitThread (0); /* Should never hit this */ +} + int __stdcall sig_send (_pinfo *p, int sig, _cygtls *tid) { @@ -1419,6 +1446,23 @@ wait_sig (VOID *) case __SIGSETPGRP: init_console_handler (true); break; + case __SIGTHREADEXIT: + { + /* Serialize thread exit as the thread exit code can be interpreted + as the process exit code in some cases when racing with + ExitProcess/TerminateProcess. + So, wait for the thread which sent this signal to exit, then + release the process lock which it held and close it's handle. + See cgf-000017 in DevNotes for more details. + */ + HANDLE h = (HANDLE) pack.si.si_value.sival_ptr; + DWORD res = WaitForSingleObject (h, 5000); + lock_process::force_release (pack.sigtls); + ForceCloseHandle1 (h, exit_thread); + if (res != WAIT_OBJECT_0) + system_printf ("WaitForSingleObject(%p) for thread exit returned %u", h, res); + } + break; default: if (pack.si.si_signo < 0) sig_clear (-pack.si.si_signo); @@ -1461,5 +1505,8 @@ wait_sig (VOID *) close_my_readsig (); sigproc_printf ("signal thread exiting"); - ExitThread (0); + /* Just wait for the process to go away. Otherwise, this thread's + exit value could be interpreted as the process exit value. + See cgf-000017 in DevNotes for more details. */ + Sleep (INFINITE); } |