summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/cygthread.cc
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/cygthread.cc')
-rw-r--r--winsup/cygwin/cygthread.cc26
1 files changed, 20 insertions, 6 deletions
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. */