From 13ce6427583eace9b739472d37e6296c30788b04 Mon Sep 17 00:00:00 2001 From: Danny Smith Date: Thu, 25 Apr 2002 22:06:14 +0000 Subject: Add atexit support for dlls. * crt1.c (atexit): Force thunk to _imp__atexit. (_onexit): Force thunk to _imp___onexit. * dllcrt1.c (DllMainCRTStartup): Initialise private atexit table on DLL_PROCESS_ATTACH, clean it up on DLL_PROCESS_DETACH. (__dll_exit): New function to run atexit-registered functions and flush output buffers on DLL_PROCESS_DETACH or failed DLL_PROCESS_ATTACH. (atexit): Force use of private atexit table via _dllonexit, (_onexit): New function. Force use of private atexit table via _dllonexit, * mscvrt.def (atexit, _onexit): Add DATA keyword so that only _imp_<_symbol> is visible in import lib. * mscvrt20.def: Likewise. * mscvrt40.def: Likewise. * crtdll.def: Likewise. --- winsup/mingw/ChangeLog | 19 +++++ winsup/mingw/crt1.c | 17 ++++ winsup/mingw/crtdll.def | 4 +- winsup/mingw/dllcrt1.c | 196 ++++++++++++++++++++++++++++++++++++++++++++++ winsup/mingw/msvcrt.def | 4 +- winsup/mingw/msvcrt20.def | 4 +- winsup/mingw/msvcrt40.def | 4 +- 7 files changed, 240 insertions(+), 8 deletions(-) create mode 100644 winsup/mingw/dllcrt1.c diff --git a/winsup/mingw/ChangeLog b/winsup/mingw/ChangeLog index 19768b45b8b..f82b2b01526 100644 --- a/winsup/mingw/ChangeLog +++ b/winsup/mingw/ChangeLog @@ -1,3 +1,22 @@ +2002-04-26 Danny Smith + + Add atexit support for dlls. + * crt1.c (atexit): Force thunk to _imp__atexit. + (_onexit): Force thunk to _imp___onexit. + * dllcrt1.c (DllMainCRTStartup): Initialise private atexit + table on DLL_PROCESS_ATTACH, clean it up on DLL_PROCESS_DETACH. + (__dll_exit): New function to run atexit-registered functions + and flush output buffers on DLL_PROCESS_DETACH or failed + DLL_PROCESS_ATTACH. + (atexit): Force use of private atexit table via _dllonexit, + (_onexit): New function. Force use of private atexit table via + _dllonexit, + * mscvrt.def (atexit, _onexit): Add DATA keyword so that only + _imp_<_symbol> is visible in import lib. + * mscvrt20.def: Likewise. + * mscvrt40.def: Likewise. + * crtdll.def: Likewise. + 2002-04-26 Danny Smith * include/fenv.h: Change header guard macro to _FENV_H_. diff --git a/winsup/mingw/crt1.c b/winsup/mingw/crt1.c index f91f1da28f1..a11c2fb039f 100644 --- a/winsup/mingw/crt1.c +++ b/winsup/mingw/crt1.c @@ -232,3 +232,20 @@ WinMainCRTStartup () __mingw_CRTStartup (); } +/* + * We force use of library version of atexit, which is only + * visible in import lib as _imp__atexit + */ +extern int (*_imp__atexit)(void (*)(void)); +int atexit (void (* pfn )(void) ) +{ + return ( (*_imp__atexit)(pfn)); +} + +/* Likewise for non-ANSI _onexit */ +extern _onexit_t (*_imp___onexit)(_onexit_t); +_onexit_t +_onexit (_onexit_t pfn ) +{ + return (*_imp___onexit)(pfn); +} diff --git a/winsup/mingw/crtdll.def b/winsup/mingw/crtdll.def index 694547471e6..6f924fb7b34 100644 --- a/winsup/mingw/crtdll.def +++ b/winsup/mingw/crtdll.def @@ -414,7 +414,7 @@ _mkdir _mktemp _msize _nextafter -_onexit +_onexit DATA _open _open_osfhandle _osmajor_dll DATA @@ -520,7 +520,7 @@ asctime asin atan atan2 -atexit +atexit DATA atof atoi atol diff --git a/winsup/mingw/dllcrt1.c b/winsup/mingw/dllcrt1.c new file mode 100644 index 00000000000..fe351eb1090 --- /dev/null +++ b/winsup/mingw/dllcrt1.c @@ -0,0 +1,196 @@ +/* + * dllcrt1.c + * + * Initialization code for DLLs. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * DLL support adapted from Gunther Ebert + * Maintained by Mumit Khan + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRENTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warrenties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ +#include +#include +#include +#include +#include +#include + +/* Unlike normal crt1, I don't initialize the FPU, because the process + * should have done that already. I also don't set the file handle modes, + * because that would be rude. */ + +#ifdef __GNUC__ +extern void __main (); +extern void __do_global_dtors (); +#endif + +typedef void (* p_atexit_fn )(void); +static p_atexit_fn* first_atexit; +static p_atexit_fn* next_atexit; + +static void +__dll_exit (void); + +/* This is based on the function in the Wine project's exit.c */ +p_atexit_fn __dllonexit (p_atexit_fn, p_atexit_fn**, p_atexit_fn**); + + +extern BOOL WINAPI DllMain (HANDLE, DWORD, LPVOID); + + +BOOL WINAPI +DllMainCRTStartup (HANDLE hDll, DWORD dwReason, LPVOID lpReserved) +{ + BOOL bRet; + + if (dwReason == DLL_PROCESS_ATTACH) + { + /* Initialize private atexit table for this dll. + 32 is min size required by ANSI */ + + first_atexit = (p_atexit_fn*) malloc (32 * sizeof (p_atexit_fn)); + if (first_atexit == NULL ) /* can't allocate memory */ + { + errno=ENOMEM; + return FALSE; + } + *first_atexit = NULL; + next_atexit = first_atexit; + +#ifdef DEBUG + printf ("%s: DLL_PROCESS_ATTACH (%d)\n", __FUNCTION__); +#endif + + +#ifdef __GNUC__ + /* From libgcc.a, __main calls global class constructors, + __do_global_ctors, which registers __do_global_dtors + as the first entry of the private atexit table we + have just initialised */ + __main (); + +#endif + } + + /* + * Call the user-supplied DllMain subroutine. + * This has to come after initialization of atexit table and + * registration of global constructors. + * NOTE: DllMain is optional, so libmingw32.a includes a stub + * which will be used if the user does not supply one. + */ + + bRet = DllMain (hDll, dwReason, lpReserved); + /* Handle case where DllMain returns FALSE on attachment attempt. */ + + if ( (dwReason == DLL_PROCESS_ATTACH) && !bRet) + { +#ifdef DEBUG + printf ("%s: DLL_PROCESS_ATTACH failed, cleaning up\n", __FUNCTION__); +#endif + + __dll_exit (); /* Cleanup now. This will set first_atexit to NULL so we + know we've cleaned up */ + } + + if (dwReason == DLL_PROCESS_DETACH) + { +#ifdef DEBUG + printf ("%s: DLL_PROCESS_DETACH (%d)\n", __FUNCTION__); +#endif + /* If not attached, return FALSE. Cleanup already done above + if failed attachment attempt. */ + if (! first_atexit ) + bRet = FALSE; + else + /* + * We used to call __do_global_dtors () here. This is + * no longer necessary since __do_global_dtors is now + * registered at start (last out) of private atexit table. + */ + __dll_exit (); + } + return bRet; +} + +static +void +__dll_exit(void) +/* Run LIFO terminators registered in private atexit table */ +{ + if ( first_atexit ) + { + p_atexit_fn* __last = next_atexit - 1; + while ( __last >= first_atexit ) + { + if ( *__last != NULL ) + { +#ifdef DEBUG + printf ("%s: Calling exit function 0x%x from 0x%x\n", + __FUNCTION__, (unsigned)(*__last),(unsigned)__last); +#endif + (**__last) (); + } + __last--; + } + free ( first_atexit ) ; + first_atexit = NULL ; + } + /* + Make sure output buffers opened by DllMain or + atexit-registered functions are flushed before detaching, + otherwise we can have problems with redirected output. + */ + fflush (NULL); +} + +/* + * The atexit exported from msvcrt.dll causes problems in DLLs. + * Here, we override the exported version of atexit with one that passes the + * private table initialised in DllMainCRTStartup to __dllonexit. + * That means we have to hide the mscvrt.dll atexit because the + * atexit defined here gets __dllonexit from the same lib. + */ + +int +atexit (p_atexit_fn pfn ) +{ +#ifdef DEBUG + printf ("%s: registering exit function 0x%x at 0x%x\n", + __FUNCTION__, (unsigned)pfn, (unsigned)next_atexit); +#endif + return (__dllonexit (pfn, &first_atexit, &next_atexit) + == NULL ? -1 : 0 ); +} + +/* + * Likewise for non-ANSI function _onexit that may be called by + * code in the dll. + */ + +_onexit_t +_onexit (_onexit_t pfn ) +{ +#ifdef DEBUG + printf ("%s: registering exit function 0x%x at 0x%x\n", + __FUNCTION__, (unsigned)pfn, (unsigned)next_atexit); +#endif + return ((_onexit_t) __dllonexit ((p_atexit_fn)pfn, &first_atexit, &next_atexit)); +} diff --git a/winsup/mingw/msvcrt.def b/winsup/mingw/msvcrt.def index 8d3e1a8cc21..0b85e9e1cb1 100644 --- a/winsup/mingw/msvcrt.def +++ b/winsup/mingw/msvcrt.def @@ -365,7 +365,7 @@ _mkdir _mktemp _msize _nextafter -_onexit +_onexit DATA _open _open_osfhandle _osver DATA @@ -546,7 +546,7 @@ asctime asin atan atan2 -atexit +atexit DATA atof atoi atol diff --git a/winsup/mingw/msvcrt20.def b/winsup/mingw/msvcrt20.def index 77ff49510cc..9ceb0750e7b 100644 --- a/winsup/mingw/msvcrt20.def +++ b/winsup/mingw/msvcrt20.def @@ -329,7 +329,7 @@ _msize _mtlock _mtunlock _nextafter -_onexit +_onexit DATA _open _open_osfhandle _osver @@ -528,7 +528,7 @@ asctime asin atan atan2 -atexit +atexit DATA atof atoi atol diff --git a/winsup/mingw/msvcrt40.def b/winsup/mingw/msvcrt40.def index 936aff962ee..e4b09f999eb 100644 --- a/winsup/mingw/msvcrt40.def +++ b/winsup/mingw/msvcrt40.def @@ -312,7 +312,7 @@ _msize _mtlock _mtunlock _nextafter -_onexit +_onexit DATA _open _open_osfhandle _osver @@ -485,7 +485,7 @@ asctime asin atan atan2 -atexit +atexit DATA atof atoi atol -- cgit v1.2.1