summaryrefslogtreecommitdiff
path: root/ptw32_throw.c
diff options
context:
space:
mode:
Diffstat (limited to 'ptw32_throw.c')
-rw-r--r--ptw32_throw.c48
1 files changed, 43 insertions, 5 deletions
diff --git a/ptw32_throw.c b/ptw32_throw.c
index a329e5c..20bfcf5 100644
--- a/ptw32_throw.c
+++ b/ptw32_throw.c
@@ -38,14 +38,22 @@
#include "pthread.h"
#include "implement.h"
-
+/*
+ * ptw32_throw
+ *
+ * All canceled and explicitly exited POSIX threads go through
+ * here. This routine knows how to exit both POSIX initiated threads and
+ * 'implicit' POSIX threads for each of the possible language modes (C,
+ * C++, and SEH).
+ */
void
ptw32_throw(DWORD exception)
{
-#ifdef __CLEANUP_C
- pthread_t self = pthread_self();
-#endif
-
+ /*
+ * Don't use pthread_self() to avoid creating an implicit POSIX thread handle
+ * unnecessarily.
+ */
+ pthread_t self = (pthread_t) pthread_getspecific (ptw32_selfThreadKey);
#ifdef __CLEANUP_SEH
DWORD exceptionInformation[3];
@@ -58,6 +66,36 @@ ptw32_throw(DWORD exception)
exit(1);
}
+ if (NULL == self || self->implicit)
+ {
+ /*
+ * We're inside a non-POSIX initialised Win32 thread
+ * so there is no point to jump or throw back to. Just do an
+ * explicit thread exit here after cleaning up POSIX
+ * residue (i.e. cleanup handlers, POSIX thread handle etc).
+ */
+ unsigned exitCode = 0;
+
+ switch (exception)
+ {
+ case PTW32_EPS_CANCEL:
+ exitCode = (unsigned) PTHREAD_CANCELED;
+ break;
+ case PTW32_EPS_EXIT:
+ exitCode = (unsigned) self->exitStatus;;
+ break;
+ }
+
+ pthread_win32_thread_detach_np();
+
+#if ! defined (__MINGW32__) || defined (__MSVCRT__)
+ _endthreadex (exitCode);
+#else
+ _endthread ();
+#endif
+
+ }
+
#ifdef __CLEANUP_SEH