From c94735ecdde19c4de652efd144faeec1a729b1e0 Mon Sep 17 00:00:00 2001 From: rpj Date: Thu, 28 Dec 2000 05:32:07 +0000 Subject: ./ChangeLog: 2000-12-28 Ross Johnson * private.c (ptw32_threadStart): Unhandled exceptions are now passed through to the system to deal with. This is consistent with normal Windows behaviour. C++ applications may use set_terminate() to override the default behaviour which is to call ptw32_terminate(). Ptw32_terminate() cleans up some POSIX thread stuff before calling the system default function which calls abort(). The users termination function should conform to standard C++ semantics which is to not return. It should exit the thread (call pthread_exit()) or exit the application. * private.c (ptw32_terminate): Added as the default set_terminate() function. It calls the system default function after cleaning up some POSIX thread stuff. * implement.h (ptw32_try_enter_critical_section): Move declaration. * global.c (ptw32_try_enter_critical_section): Moved from dll.c. * dll.c: Move process and thread attach/detach code into functions in nonportable.c. * nonportable.c (pthread_win32_process_attach_np): Process attach code from dll.c is now available to static linked applications. * nonportable.c (pthread_win32_process_detach_np): Likewise. * nonportable.c (pthread_win32_thread_attach_np): Likewise. * nonportable.c (pthread_win32_thread_detach_np): Likewise. * pthread.h: Add new non-portable prototypes for static linked applications. * GNUmakefile (OPT): Increase optimisation flag and remove debug info flag. * pthread.def: Add new non-portable exports for static linked applications. 2000-12-11 Ross Johnson * FAQ: Update Answer 6 re getting a fully working Mingw32 built library. 2000-09-09 Ross Johnson * pthread.h (ctime_r): Fix arg. ./tests/ChangeLog: 2000-12-28 Ross Johnson * eyal1.c: Increase thread work loads. * exception2.c: New test. * exception3.c: New test. * Makefile: Add new tests exception2.c and exception3.c. * GNUmakefile: Likewise. 2000-12-11 Ross Johnson * cleanup3.c: Remove unused variable. * cleanup2.c: Likewise. * exception1.c: Throw an exception rather than use a deliberate zero divide so that catch(...) will handle it under Mingw32. Mingw32 now builds the library correctly to pass all tests - see Thomas Pfaff's detailed instructions re needed changes to Mingw32 in the Pthreads-Win32 FAQ. --- private.c | 157 +++++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 115 insertions(+), 42 deletions(-) (limited to 'private.c') diff --git a/private.c b/private.c index 0e94d5f..977eb67 100644 --- a/private.c +++ b/private.c @@ -154,22 +154,77 @@ ptw32_processTerminate (void) } /* processTerminate */ -#ifdef _MSC_VER +#if defined(_MSC_VER) && !defined(__cplusplus) static DWORD ExceptionFilter (EXCEPTION_POINTERS * ep, DWORD * ei) { - DWORD param; - DWORD numParams = ep->ExceptionRecord->NumberParameters; - - numParams = (numParams > 3) ? 3 : numParams; - - for (param = 0; param < numParams; param++) + switch (ep->ExceptionRecord->ExceptionCode) { - ei[param] = ep->ExceptionRecord->ExceptionInformation[param]; + case EXCEPTION_PTW32_SERVICES: + { + DWORD param; + DWORD numParams = ep->ExceptionRecord->NumberParameters; + + numParams = (numParams > 3) ? 3 : numParams; + + for (param = 0; param < numParams; param++) + { + ei[param] = ep->ExceptionRecord->ExceptionInformation[param]; + } + + return EXCEPTION_EXECUTE_HANDLER; + break; + } + default: + { + /* + * A system unexpected exception has occurred running the user's + * routine. We need to cleanup before letting the exception + * out of thread scope. + */ + pthread_t self = pthread_self(); + + (void) pthread_mutex_destroy(&self->cancelLock); + ptw32_callUserDestroyRoutines(self); + + return EXCEPTION_CONTINUE_SEARCH; + break; + } } +} + +#elif defined(__cplusplus) + +#if defined(_MSC_VER) +#include +static terminate_function ptw32_oldTerminate; +#else +#include +static terminate_handler ptw32_oldTerminate; +#endif - return EXCEPTION_EXECUTE_HANDLER; +#if 0 +#include +static pthread_mutex_t termLock = PTHREAD_MUTEX_INITIALIZER; +#endif + +void +ptw32_terminate () +{ + pthread_t self = pthread_self(); +#if 0 + FILE * fp; + pthread_mutex_lock(&termLock); + fp = fopen("pthread.log", "a"); + fprintf(fp, "Terminate\n"); + fclose(fp); + pthread_mutex_unlock(&termLock); +#endif + set_terminate(ptw32_oldTerminate); + (void) pthread_mutex_destroy(&self->cancelLock); + ptw32_callUserDestroyRoutines(self); + terminate(); } #endif /* _MSC_VER */ @@ -189,7 +244,7 @@ ptw32_threadStart (ThreadParms * threadParms) DWORD ei[] = {0,0,0}; #endif - void * status; + void * status = (void *) 0; self = threadParms->tid; start = threadParms->start; @@ -226,53 +281,64 @@ ptw32_threadStart (ThreadParms * threadParms) } __except (ExceptionFilter(GetExceptionInformation(), ei)) { - DWORD ec = GetExceptionCode(); - - if (ec == EXCEPTION_PTW32_SERVICES) - { - switch (ei[0]) - { - case PTW32_EPS_CANCEL: - status = PTHREAD_CANCELED; - break; - case PTW32_EPS_EXIT: - status = self->exitStatus; - break; - default: - status = PTHREAD_CANCELED; + switch (ei[0]) + { + case PTW32_EPS_CANCEL: + status = PTHREAD_CANCELED; break; - } - } - else - { - /* - * A system unexpected exception had occurred running the user's - * routine. We get control back within this block because - * we can't allow the exception to pass out of thread scope. - */ - status = PTHREAD_CANCELED; - } + case PTW32_EPS_EXIT: + status = self->exitStatus; + break; + default: + status = PTHREAD_CANCELED; + break; + } } #else /* _MSC_VER && !__cplusplus */ #ifdef __cplusplus + ptw32_oldTerminate = set_terminate(&ptw32_terminate); + try { /* - * Run the caller's routine; + * Run the caller's routine in a nested try block so that we + * can run the user's terminate function, which may call + * pthread_exit() or be canceled. */ - status = self->exitStatus = (*start) (arg); + try + { + status = self->exitStatus = (*start) (arg); + } + catch (ptw32_exception &) + { + /* + * Pass these through to the outer block. + */ + throw; + } + catch(...) + { + /* + * We want to run the user's terminate function if supplied. + * That function may call pthread_exit() or be canceled, which will + * be handled by the outer try block. + * + * ptw32_terminate() will be called if there is no user supplied function. + */ + (void) terminate(); + } } - catch (ptw32_exception_cancel) + catch (ptw32_exception_cancel &) { /* * Thread was cancelled. */ status = self->exitStatus = PTHREAD_CANCELED; } - catch (ptw32_exception_exit) + catch (ptw32_exception_exit &) { /* * Thread was exited via pthread_exit(). @@ -282,11 +348,18 @@ ptw32_threadStart (ThreadParms * threadParms) catch (...) { /* - * A system unexpected exception had occurred running the user's - * routine. We get control back within this block because - * we can't allow the exception out of thread scope. + * A system unexpected exception has occurred running the user's + * terminate routine. We get control back within this block - cleanup + * and release the exception out of thread scope. */ status = self->exitStatus = PTHREAD_CANCELED; + (void) pthread_mutex_destroy(&self->cancelLock); + ptw32_callUserDestroyRoutines(self); + throw; + + /* + * Never reached. + */ } #else /* __cplusplus */ -- cgit v1.2.3