Wrapping atexit() is a bad idea on Windows, where the EXE and each DLL

2005-08-31  Tor Lillqvist  <tml@novell.com>

	* glib/gutils.h: Wrapping atexit() is a bad idea on Windows, where
	the EXE and each DLL have their own atexit function chains.

	#define g_atexit as atexit instead. This means it has a
	better chance of doing what the caller wants. For instance,
	gtkhtml calls g_atexit() registering a function in gtkhtml
	itself. This caused a crash when g_atexit() was implemented as a
	function in the GLib DLL. The gtkhtml DLL was already unloaded by
	the time the GLib DLL got unloaded.

	* glib/gutils.c: #undef the #define mentioned above, to also get a
	real g_atexit() into the DLL for backward compatibility. Document
	the Windows behaviour of g_atexit(), and document the varying ways
	atexit() can behave in the context of dynamically loaded modules
	on Unix.
This commit is contained in:
Tor Lillqvist
2005-08-31 21:02:47 +00:00
committed by Tor Lillqvist
parent 49003b01ff
commit 130763338c
5 changed files with 98 additions and 0 deletions

View File

@@ -208,11 +208,44 @@ g_memmove (gpointer dest,
}
#endif /* !HAVE_MEMMOVE && !HAVE_WORKING_BCOPY */
#ifdef G_OS_WIN32
#undef g_atexit
#endif
/**
* g_atexit:
* @func: the function to call on normal program termination.
*
* Specifies a function to be called at normal program termination.
*
* Since GLib 2.8.2, on Windows g_atexit() actually is a preprocessor
* macro that maps to a call to the atexit() function in the C
* library. This means that in case the code that calls g_atexit(),
* i.e. atexit(), is in a DLL, the function will be called when the
* DLL is detached from the program. This typically makes more sense
* than that the function is called when the GLib DLL is detached,
* which happened earlier when g_atexit() was a function in the GLib
* DLL.
*
* The behaviour of atexit() in the context of dynamically loaded
* modules is not formally specified and varies wildly.
*
* On POSIX systems, calling g_atexit() (or atexit()) in a dynamically
* loaded module which is unloaded before the program terminates might
* well cause a crash at program exit.
*
* Some POSIX systems implement atexit() like Windows, and have each
* dynamically loaded module maintain an own atexit chain that is
* called when the module is unloaded.
*
* On other POSIX systems, before a dynamically loaded module is
* unloaded, the registered atexit functions (if any) residing in that
* module are called, regardless where the code that registered them
* resided. This is presumably the most robust approach.
*
* As can be seen from the above, for portability it's best to avoid
* calling g_atexit() (or atexit()) except in the main executable of a
* program.
*/
void
g_atexit (GVoidFunc func)