Introduce our own shutdown callback mechanism.

Instead of adding stuff to `_shutdown()`, we can now register a shutdown
routine from the respective `init()` function of our modules.

This also has the advantage, that we're sure they're called in reverse
order from how the initialization happened.

I didn't simply use `atexit()` because POSIX says that the number of
possible callbacks is limited (min 32) and I was not sure whether
we will maybe extend this number at one point.

Signed-off-by: Steffen Jaeckel <s@jaeckel.eu>
This commit is contained in:
Steffen Jaeckel
2025-03-07 11:44:31 +01:00
parent 662a0be633
commit c5a131ee46
39 changed files with 321 additions and 327 deletions

View File

@@ -220,8 +220,7 @@ _init(char* log_level, char* config_file, char* log_file, char* theme_name)
auto_gchar gchar* prof_version = prof_get_version();
log_info("Starting Profanity (%s)…", prof_version);
chat_log_init();
groupchat_log_init();
chatlog_init();
accounts_load();
if (theme_name) {
@@ -261,6 +260,47 @@ _init(char* log_level, char* config_file, char* log_file, char* theme_name)
ui_resize();
}
static GList* shutdown_routines = NULL;
/* We have to encapsulate the function pointer, since the C standard does not guarantee
* that a void* can be converted to a function* and vice-versa.
*/
struct shutdown_routine
{
void (*routine)(void);
};
static gint
_cmp_shutdown_routine(const struct shutdown_routine* a, const struct shutdown_routine* b)
{
return a->routine != b->routine;
}
void
prof_add_shutdown_routine(void (*routine)(void))
{
struct shutdown_routine this = { .routine = routine };
if (g_list_find_custom(shutdown_routines, &this, (GCompareFunc)_cmp_shutdown_routine)) {
return;
}
struct shutdown_routine* r = malloc(sizeof *r);
r->routine = routine;
shutdown_routines = g_list_prepend(shutdown_routines, r);
}
static void
_call_and_free_shutdown_routine(struct shutdown_routine* r)
{
r->routine();
free(r);
}
void
prof_shutdown(void)
{
g_list_free_full(shutdown_routines, (GDestroyNotify)_call_and_free_shutdown_routine);
}
static void
_shutdown(void)
{
@@ -276,30 +316,9 @@ _shutdown(void)
if (conn_status == JABBER_CONNECTED) {
cl_ev_disconnect();
}
#ifdef HAVE_GTK
tray_shutdown();
#endif
session_shutdown();
plugins_on_shutdown();
muc_close();
caps_close();
#ifdef HAVE_LIBOTR
otr_shutdown();
#endif
#ifdef HAVE_LIBGPGME
p_gpg_close();
#endif
#ifdef HAVE_OMEMO
omemo_close();
#endif
chat_log_close();
theme_close();
accounts_close();
tlscerts_close();
log_stderr_close();
plugins_shutdown();
cmd_uninit();
ui_close();
prof_shutdown();
/* Prefs and logs have to be closed in swapped order, so they're no using the automatic
* shutdown mechanism. */
prefs_close();
log_close();
}