diff options
author | davygrvy <davygrvy@pobox.com> | 2004-05-06 01:04:32 (GMT) |
---|---|---|
committer | davygrvy <davygrvy@pobox.com> | 2004-05-06 01:04:32 (GMT) |
commit | 2cdf4d07e53202f69d06d9c388f89198b0f16f5f (patch) | |
tree | 0fefbc9944f24dde0b591b48c834a8db9ec80ea5 /win/tclWin32Dll.c | |
parent | e545850e9721d9936caa3475993a988c63f3ec65 (diff) | |
download | tcl-2cdf4d07e53202f69d06d9c388f89198b0f16f5f.zip tcl-2cdf4d07e53202f69d06d9c388f89198b0f16f5f.tar.gz tcl-2cdf4d07e53202f69d06d9c388f89198b0f16f5f.tar.bz2 |
* win/tclWin32Dll.c: Structured Exception Handling added around
Tcl_Finalize called from DllMain's DLL_PROCESS_DETACH. We can't
be 100% assured that Tcl is being unloaded by the OS in a stable
condition and we need to protect the exit handlers should the
stack be in a hosed state. AT&T style assembly for SEH under
MinGW included, too. [Patch 858493]
Also added DisableThreadLibraryCalls() for the DLL_PROCESS_ATTACH
case. We're not interested in knowing about DLL_THREAD_ATTACH, so
disable the notices.
Diffstat (limited to 'win/tclWin32Dll.c')
-rw-r--r-- | win/tclWin32Dll.c | 85 |
1 files changed, 82 insertions, 3 deletions
diff --git a/win/tclWin32Dll.c b/win/tclWin32Dll.c index 2e341bc..2e3368c 100644 --- a/win/tclWin32Dll.c +++ b/win/tclWin32Dll.c @@ -9,7 +9,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclWin32Dll.c,v 1.24.2.1 2003/04/14 15:45:59 vincentdarley Exp $ + * RCS: @(#) $Id: tclWin32Dll.c,v 1.24.2.2 2004/05/06 01:04:32 davygrvy Exp $ */ #include "tclWinInt.h" @@ -239,19 +239,98 @@ DllMain(hInst, reason, reserved) { switch (reason) { case DLL_PROCESS_ATTACH: + DisableThreadLibraryCalls(hInst); TclWinInit(hInst); return TRUE; case DLL_PROCESS_DETACH: - if (hInst == hInstance) { - Tcl_Finalize(); + /* + * Protect the call to Tcl_Finalize. The OS could be unloading + * us from an exception handler and the state of the stack might + * be unstable. + */ +#ifdef HAVE_NO_SEH +# ifdef TCL_MEM_DEBUG + __asm__ __volatile__ ( + "movl %%esp, %0" "\n\t" + "movl %%ebp, %1" "\n\t" + "movl %%fs:0, %2" "\n\t" + : "=m"(INITIAL_ESP), + "=m"(INITIAL_EBP), + "=r"(INITIAL_HANDLER) ); +# endif /* TCL_MEM_DEBUG */ + + __asm__ __volatile__ ( + "pushl %ebp" "\n\t" + "pushl $__except_dllmain_detach_handler" "\n\t" + "pushl %fs:0" "\n\t" + "movl %esp, %fs:0"); +#else + __try { +#endif /* HAVE_NO_SEH */ + + Tcl_Finalize(); + +#ifdef HAVE_NO_SEH + __asm__ __volatile__ ( + "jmp dllmain_detach_pop" "\n" + "dllmain_detach_reentry:" "\n\t" + "movl %%fs:0, %%eax" "\n\t" + "movl 0x8(%%eax), %%esp" "\n\t" + "movl 0x8(%%esp), %%ebp" "\n" + "dllmain_detach_pop:" "\n\t" + "movl (%%esp), %%eax" "\n\t" + "movl %%eax, %%fs:0" "\n\t" + "add $12, %%esp" "\n\t" + : + : + : "%eax"); + +# ifdef TCL_MEM_DEBUG + __asm__ __volatile__ ( + "movl %%esp, %0" "\n\t" + "movl %%ebp, %1" "\n\t" + "movl %%fs:0, %2" "\n\t" + : "=m"(RESTORED_ESP), + "=m"(RESTORED_EBP), + "=r"(RESTORED_HANDLER) ); + + if (INITIAL_ESP != RESTORED_ESP) + Tcl_Panic("ESP restored incorrectly"); + if (INITIAL_EBP != RESTORED_EBP) + Tcl_Panic("EBP restored incorrectly"); + if (INITIAL_HANDLER != RESTORED_HANDLER) + Tcl_Panic("HANDLER restored incorrectly"); +# endif /* TCL_MEM_DEBUG */ +#else + } __except (EXCEPTION_EXECUTE_HANDLER) { + /* empty handler body. */ } +#endif /* HAVE_NO_SEH */ break; } return TRUE; } +#ifdef HAVE_NO_SEH +static +__attribute__ ((cdecl)) +EXCEPTION_DISPOSITION +_except_dllmain_detach_handler( + struct _EXCEPTION_RECORD *ExceptionRecord, + void *EstablisherFrame, + struct _CONTEXT *ContextRecord, + void *DispatcherContext) +{ + __asm__ __volatile__ ( + "jmp dllmain_detach_reentry"); + /* Nuke compiler warning about unused static function */ + _except_dllmain_detach_handler(NULL, NULL, NULL, NULL); + return 0; /* Function does not return */ +} +#endif /* HAVE_NO_SEH */ + #endif /* !STATIC_BUILD */ #endif /* __WIN32__ */ |