From 8d2e05f5ef5d72baa05ea9ebf6c6b58ace6d6a68 Mon Sep 17 00:00:00 2001 From: Bram Matthys Date: Sat, 9 May 2020 11:58:26 +0200 Subject: [PATCH] Fix crash when combining +P with a 3rd party module, or actually any parameter channel mode module loaded after channeldb. Reported by GaMbiTo, with help from PeGaSuS, Gottem and k4be in https://bugs.unrealircd.org/view.php?id=5669 It is not safe to call channel mode parameter functions when unloading modules. Makes sense I think. We now no longer write the db on rehash, which is something i didn't like anyway (wasted CPU cycles). The problem was that one could not just scratch the write db call, as otherwise if someone rehashes every minute would cause the db never to be saved. This is because on each rehash the event to write the db gets rescheduled to +5 minutes in the future. We now work around that in the same way as connthrottle does. Obviously it would be better to make the event system itself deal with this, but that is (way) too much for now. --- src/modules/channeldb.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/modules/channeldb.c b/src/modules/channeldb.c index 882fbd641..5f4a9315e 100644 --- a/src/modules/channeldb.c +++ b/src/modules/channeldb.c @@ -67,7 +67,7 @@ struct cfgstruct { }; static struct cfgstruct cfg; -static int channeldb_loaded = 0; +static long channeldb_next_event = 0; MOD_TEST() { @@ -80,7 +80,7 @@ MOD_INIT() { MARK_AS_OFFICIAL_MODULE(modinfo); - LoadPersistentInt(modinfo, channeldb_loaded); + LoadPersistentLong(modinfo, channeldb_next_event); setcfg(); @@ -90,7 +90,7 @@ MOD_INIT() MOD_LOAD() { - if (!channeldb_loaded) + if (!channeldb_next_event) { /* If this is the first time that our module is loaded, then read the database. */ if (!read_channeldb()) @@ -102,9 +102,9 @@ MOD_LOAD() else config_warn("[channeldb] Failed to rename database from %s to %s: %s", cfg.database, fname, strerror(errno)); } - channeldb_loaded = 1; + channeldb_next_event = TStime() + CHANNELDB_SAVE_EVERY; } - EventAdd(modinfo->handle, "channeldb_write_channeldb", write_channeldb_evt, NULL, CHANNELDB_SAVE_EVERY*1000, 0); + EventAdd(modinfo->handle, "channeldb_write_channeldb", write_channeldb_evt, NULL, 1000, 0); if (ModuleGetError(modinfo->handle) != MODERR_NOERROR) { config_error("A critical error occurred when loading module %s: %s", MOD_HEADER.name, ModuleGetErrorStr(modinfo->handle)); @@ -115,9 +115,8 @@ MOD_LOAD() MOD_UNLOAD() { - write_channeldb(); freecfg(); - SavePersistentInt(modinfo, channeldb_loaded); + SavePersistentLong(modinfo, channeldb_next_event); return MOD_SUCCESS; } @@ -191,6 +190,9 @@ int channeldb_configrun(ConfigFile *cf, ConfigEntry *ce, int type) EVENT(write_channeldb_evt) { + if (channeldb_next_event > TStime()) + return; + channeldb_next_event = TStime() + CHANNELDB_SAVE_EVERY; write_channeldb(); }