gtk_quit_add() removed in GTK 3 with no replacement
Submitted by Lennart Poettering
Link to original bug (#639770)
Description
libcanberra relied on GTK2's gtk_quit_add() to flush its event sound queue before an application is going down. Since gtk_quit_add() got removed from GTK3 without replacement libcanberra currently cannot be compiled against it.
We need some kind of replacement for gtk_quit_add() in either gtk or glib, for cases like libcanberra where some (non-essential) work needs to be done at shutdown where the full Gtk/Glib stack is still up and all libraries still initialized. While application code probably won't need this, code that is either loaded as a dynamic library or as loadable module and hence cannot simply be called from the main() function might need functionality like this.
libcanberra queues sound events in a local queue before dispatching them to the sound server to ensure that normal GdkEvent handling is not unnecessarily delayed (e.g. by CPU intensive work such as to uncompressing vorbis files) and events can be coalesced. That queue must be dispatched before the app terminates so that no event sounds are lost (i.e. somebody presses a quit button and you want the button sound to be heard before the app is gone) -- however the sound events are not really essential so it is fine if they are lost if the app terminates abnormally due to crashing.
In some other cases quit hooks like this are very much necessary too. Example: in some cases GIO will buffer data that is written out in-process. To ensure that this is sync'ed out code must manually sync it. While this is easily done from apps, this is impossible to do from loadable modules/shared libraries if there is no way to hook into the application shutdown process.
g_atexit() or GCC destructors are no suitable option since the thread context and their execution order is not defined. The dispatching of the event sound queue (or gio buffer syncs) must take place at a time where all libraries are still initialized which basically means that this must be done from within the glib main loop code -- and not after main() has terminated as would happen with atexit().