Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Faylor <me@cgf.cx>2012-12-21 22:52:00 +0400
committerChristopher Faylor <me@cgf.cx>2012-12-21 22:52:00 +0400
commit614aff88a0cf6c0ec5ec5ba063b003549dedc9db (patch)
treef750a571791d6d564bc7a5a252e2f2b78f22ec74 /winsup/cygwin/sigproc.cc
parentdfbb1d0383420c383b8f0bc3149d4b76fa51b398 (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.cc49
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);
}