From 4ee52924a61bdb2fd8ce7b64d111cf7df4d19fe3 Mon Sep 17 00:00:00 2001 From: Christopher Faylor Date: Thu, 23 Dec 2004 14:57:08 +0000 Subject: * cygthread.cc (cygthread::stub): Detect if thread function wants to release itself here, to avoid a race. (cygthread::release): Clear more stuff. Add a diagnostic for an internal error. * cygthread.h (auto_release): New function. * pinfo.h (pinfo::remember): Add an argument to denote whether child is detached. * fork.cc (fork_parent): Reflect change in arguments to pinfo::remember. * pinfo.cc (_pinfo::exit): Signal exit more forcibly. (proc_waiter): Use cygthread::auto_release to signify that cygthread::stub should release the thread. This should avoid a race. (pinfo::alert_parent): Don't signify an error when wr_proc_pipe == NULL. * sigproc.cc (proc_subproc): Add support for PROC_DETACHED_CHILD. * sigproc.h: Ditto. * spawn.cc (spawn_guts): Specify whether child is detached or not when calling pinfo::remember. --- winsup/cygwin/cygthread.cc | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) (limited to 'winsup/cygwin/cygthread.cc') diff --git a/winsup/cygwin/cygthread.cc b/winsup/cygwin/cygthread.cc index 949f4716c..bca2b28f8 100644 --- a/winsup/cygwin/cygthread.cc +++ b/winsup/cygwin/cygthread.cc @@ -69,13 +69,21 @@ cygthread::stub (VOID *arg) info->func (info->arg == cygself ? info : info->arg); /* ...so the above should always return */ + /* If stack_ptr is NULL, the above function has set that to indicate + that it doesn't want to alert anyone with a SetEvent and should + just be marked as no longer inuse. Hopefully the function knows + that it is doing. */ + if (!info->func) + info->release (false); + else + { #ifdef DEBUGGING - info->func = NULL; // catch erroneous activation - info->__oldname = info->__name; + info->func = NULL; // catch erroneous activation + info->__oldname = info->__name; #endif - info->__name = NULL; - if (info->inuse) - SetEvent (info->ev); + info->__name = NULL; + SetEvent (info->ev); + } } switch (WaitForSingleObject (info->thread_sync, INFINITE)) { @@ -231,7 +239,13 @@ cygthread::release (bool nuke_h) __oldname = __name; __name = NULL; stack_ptr = NULL; - (void) InterlockedExchange (&inuse, 0); /* No longer in use */ + func = NULL; + if (!InterlockedExchange (&inuse, 0)) +#ifdef DEBUGGING + api_fatal ("released a thread that was not inuse"); +#else + system_printf ("released a thread that was not inuse"); +#endif } /* Forcibly terminate a thread. */ -- cgit v1.2.3