summaryrefslogtreecommitdiff
path: root/private.c
diff options
context:
space:
mode:
Diffstat (limited to 'private.c')
-rw-r--r--private.c151
1 files changed, 106 insertions, 45 deletions
diff --git a/private.c b/private.c
index ee3ab52..5274da9 100644
--- a/private.c
+++ b/private.c
@@ -24,12 +24,7 @@
* MA 02111-1307, USA
*/
-#if !defined(_MSC_VER) && !defined(__cplusplus) && defined(__GNUC__)
-
-#warning Compile __FILE__ as C++ or thread cancellation will not work properly.
-
-#endif /* !_MSC_VER && !__cplusplus && __GNUC__ */
-
+#include <process.h>
#ifndef NEED_FTIME
#include <sys/timeb.h>
#endif
@@ -154,7 +149,7 @@ ptw32_processTerminate (void)
} /* processTerminate */
-#if defined(_MSC_VER) && !defined(__cplusplus)
+#ifdef __CLEANUP_SEH
static DWORD
ExceptionFilter (EXCEPTION_POINTERS * ep, DWORD * ei)
@@ -194,7 +189,7 @@ ExceptionFilter (EXCEPTION_POINTERS * ep, DWORD * ei)
}
}
-#elif defined(__cplusplus)
+#elif defined(__CLEANUP_CXX)
#if defined(_MSC_VER)
#include <eh.h>
@@ -230,20 +225,25 @@ ptw32_terminate ()
#endif /* _MSC_VER */
#if ! defined (__MINGW32__) || defined (__MSVCRT__)
-unsigned PT_STDCALL
+unsigned __stdcall
#else
void
#endif
-ptw32_threadStart (ThreadParms * threadParms)
+ptw32_threadStart (void * vthreadParms)
{
+ ThreadParms *threadParms = (ThreadParms *) vthreadParms;
pthread_t self;
void *(*start) (void *);
void *arg;
-#if defined(_MSC_VER) && !defined(__cplusplus)
+#ifdef __CLEANUP_SEH
DWORD ei[] = {0,0,0};
#endif
+#ifdef __CLEANUP_C
+ int setjmp_rc;
+#endif
+
void * status = (void *) 0;
self = threadParms->tid;
@@ -270,7 +270,7 @@ ptw32_threadStart (ThreadParms * threadParms)
pthread_setspecific (ptw32_selfThreadKey, self);
-#if defined(_MSC_VER) && !defined(__cplusplus)
+#ifdef __CLEANUP_SEH
__try
{
@@ -295,9 +295,39 @@ ptw32_threadStart (ThreadParms * threadParms)
}
}
-#else /* _MSC_VER && !__cplusplus */
+#else /* __CLEANUP_SEH */
-#ifdef __cplusplus
+#ifdef __CLEANUP_C
+
+ setjmp_rc = setjmp( self->start_mark );
+
+ if( 0 == setjmp_rc ) {
+
+ /*
+ * Run the caller's routine;
+ */
+ status = self->exitStatus = (*start) (arg);
+ }
+
+ else {
+
+ switch (setjmp_rc)
+ {
+ case PTW32_EPS_CANCEL:
+ status = PTHREAD_CANCELED;
+ break;
+ case PTW32_EPS_EXIT:
+ status = self->exitStatus;
+ break;
+ default:
+ status = PTHREAD_CANCELED;
+ break;
+ }
+ }
+
+#else /* __CLEANUP_C */
+
+#ifdef __CLEANUP_CXX
ptw32_oldTerminate = set_terminate(&ptw32_terminate);
@@ -328,7 +358,30 @@ ptw32_threadStart (ThreadParms * threadParms)
*
* ptw32_terminate() will be called if there is no user supplied function.
*/
- (void) terminate();
+
+ //Original invocation:
+ //(void) terminate();
+
+
+ //New invocation:
+ // a) get pointer to the termination function
+#if defined(_MSC_VER)
+ terminate_function term_func = set_terminate(0);
+#else
+ terminate_handler term_func = set_terminate(0);
+#endif
+
+ set_terminate(term_func);
+
+ // b) call the termination function (if any)
+ if (term_func != 0) {
+ term_func();
+ }
+
+ // c) if there was no termination function or the termination function did
+ // not exit thread/process, (we got this far), propagate the exception on!
+ // (should be caught by the second level try/catch block below)
+ throw;
}
}
catch (ptw32_exception_cancel &)
@@ -365,17 +418,14 @@ ptw32_threadStart (ThreadParms * threadParms)
(void) set_terminate(ptw32_oldTerminate);
-#else /* __cplusplus */
+#else
- /*
- * Run the caller's routine; no cancelation or other exceptions will
- * be honoured.
- */
- status = self->exitStatus = (*start) (arg);
+#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined.
-#endif /* __cplusplus */
+#endif /* __CLEANUP_CXX */
+#endif /* __CLEANUP_C */
+#endif /* __CLEANUP_SEH */
-#endif /* _MSC_VER */
(void) pthread_mutex_destroy(&self->cancelLock);
@@ -637,19 +687,6 @@ ptw32_callUserDestroyRoutines (pthread_t thread)
if (value != NULL && k->destructor != NULL)
{
-#if defined(_MSC_VER) && !defined(__cplusplus)
-
- /*
- * Run the caller's cleanup routine.
- *
- * If an exception occurs we let the system handle it
- * as an unhandled exception. Since we are leaving the
- * thread we should not get any internal pthreads
- * exceptions.
- */
- (*(k->destructor)) (value);
-
-#else /* _MSC_VER && !__cplusplus */
#ifdef __cplusplus
try
@@ -681,7 +718,6 @@ ptw32_callUserDestroyRoutines (pthread_t thread)
(*(k->destructor)) (value);
#endif /* __cplusplus */
-#endif /* _MSC_VER */
}
}
@@ -895,7 +931,7 @@ ptw32_sem_timedwait (sem_t * sem, const struct timespec * abstime)
DWORD
ptw32_get_exception_services_code(void)
{
-#if defined(_MSC_VER) && !defined(__cplusplus)
+#ifdef __CLEANUP_SEH
return EXCEPTION_PTW32_SERVICES;
@@ -910,10 +946,13 @@ ptw32_get_exception_services_code(void)
void
ptw32_throw(DWORD exception)
{
-#if defined(_MSC_VER) && !defined(__cplusplus)
+#ifdef __CLEANUP_C
+ pthread_t self = pthread_self();
+#endif
- DWORD exceptionInformation[3];
+#ifdef __CLEANUP_SEH
+ DWORD exceptionInformation[3];
#endif
if (exception != PTW32_EPS_CANCEL &&
@@ -923,7 +962,8 @@ ptw32_throw(DWORD exception)
exit(1);
}
-#if defined(_MSC_VER) && !defined(__cplusplus)
+#ifdef __CLEANUP_SEH
+
exceptionInformation[0] = (DWORD) (exception);
exceptionInformation[1] = (DWORD) (0);
@@ -935,9 +975,17 @@ ptw32_throw(DWORD exception)
3,
exceptionInformation);
-#else /* _MSC_VER && ! __cplusplus */
+#else /* __CLEANUP_SEH */
+
+#ifdef __CLEANUP_C
-# ifdef __cplusplus
+ ptw32_pop_cleanup_all( 1 );
+
+ longjmp( self->start_mark, exception );
+
+#else /* __CLEANUP_C */
+
+#ifdef __CLEANUP_CXX
switch (exception)
{
@@ -949,9 +997,22 @@ ptw32_throw(DWORD exception)
break;
}
-# endif /* __cplusplus */
+#else
-#endif /* _MSC_VER && ! __cplusplus */
+#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined.
+
+#endif /* __CLEANUP_CXX */
+
+#endif /* __CLEANUP_C */
+
+#endif /* __CLEANUP_SEH */
/* Never reached */
}
+
+void
+ptw32_pop_cleanup_all(int execute)
+{
+ while( NULL != ptw32_pop_cleanup(execute) ) {
+ }
+}