mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-26 14:06:15 +01:00
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:
parent
49003b01ff
commit
130763338c
18
ChangeLog
18
ChangeLog
@ -1,3 +1,21 @@
|
||||
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.
|
||||
|
||||
2005-08-31 Matthias Clasen <mclasen@redhat.com>
|
||||
|
||||
* glib/glib.symbols:
|
||||
|
@ -1,3 +1,21 @@
|
||||
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.
|
||||
|
||||
2005-08-31 Matthias Clasen <mclasen@redhat.com>
|
||||
|
||||
* glib/glib.symbols:
|
||||
|
@ -1,3 +1,21 @@
|
||||
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.
|
||||
|
||||
2005-08-31 Matthias Clasen <mclasen@redhat.com>
|
||||
|
||||
* glib/glib.symbols:
|
||||
|
@ -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)
|
||||
|
@ -229,6 +229,17 @@ typedef void (*GVoidFunc) (void);
|
||||
*/
|
||||
void g_atexit (GVoidFunc func);
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
/* It's a bad idea to wrap atexit() on Windows. If the GLib DLL calls
|
||||
* atexit(), the function will be called when the GLib DLL is detached
|
||||
* from the program, which is not what the caller wants. The caller
|
||||
* wants the function to be called when it *itself* exits (or is
|
||||
* detached, in case the caller, too, is a DLL).
|
||||
*/
|
||||
int atexit (void (*)(void));
|
||||
#define g_atexit(func) atexit(func)
|
||||
#endif
|
||||
|
||||
/* Look for an executable in PATH, following execvp() rules */
|
||||
gchar* g_find_program_in_path (const gchar *program);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user