diff --git a/include/modules.h b/include/modules.h index 97fc11a93..2dc636a2e 100644 --- a/include/modules.h +++ b/include/modules.h @@ -777,9 +777,15 @@ struct Module #define MOD_OPT_OFFICIAL 0x0002 /* Official module, do not set "tainted" */ #define MOD_OPT_PERM_RELOADABLE 0x0004 /* Module is semi-permanent: it can be re-loaded but not un-loaded */ #define MOD_OPT_GLOBAL 0x0008 /* Module is required to be loaded globally (i.e. across the entire network) */ -#define MOD_OPT_UNLOAD_PRIORITY 0x1000 /* Module wants a higher or lower unload priority */ +#define MOD_OPT_PRIORITY 0x1000 /* Module wants a higher or lower priority for unloading, init, load, etc */ +#define MOD_OPT_UNLOAD_PRIORITY 0x1000 /* Alias for MOD_OPT_PRIORITY */ #define MOD_Dep(name, container,module) {#name, (vFP *) &container, module} +/** Websocket module should init 'first' because it handles sockets */ +#define WEBSOCKET_MODULE_PRIORITY_INIT -1000000000 +/** Websocket module should unload 'last' because it handles sockets */ +#define WEBSOCKET_MODULE_PRIORITY_UNLOAD 1000000000 + /** Event structs */ struct Event { Event *prev; /**< Previous event (linked list) */ diff --git a/src/conf.c b/src/conf.c index 896be270e..1a3f93b9a 100644 --- a/src/conf.c +++ b/src/conf.c @@ -2091,8 +2091,6 @@ int config_test(void) safe_strdup(old_pid_file, conf_files->pid_file); unrealdns_delasyncconnects(); config_rehash(); - Unload_all_loaded_modules(); - /* Notify permanent modules of the rehash */ for (h = Hooks[HOOKTYPE_REHASH]; h; h = h->next) { @@ -2102,6 +2100,8 @@ int config_test(void) continue; (*(h->func.intfunc))(); } + /* Last step: */ + Unload_all_loaded_modules(); } config_pre_run_log(); diff --git a/src/modules.c b/src/modules.c index 627b66e40..3d214b572 100644 --- a/src/modules.c +++ b/src/modules.c @@ -430,18 +430,19 @@ const char *Module_Create(const char *path_) if (Mod_Handle) *Mod_Handle = mod; irc_dlsym(Mod, "Mod_Test", Mod_Test); + /* add module here, so ModuleSetOptions() w/MOD_OPT_PRIORITY is available in Mod_Test() */ + AddListItemPrio(mod, Modules, 0); if (Mod_Test) { - if ((ret = (*Mod_Test)(&mod->modinfo)) < MOD_SUCCESS) { - ircsnprintf(errorbuf, sizeof(errorbuf), "Mod_Test returned %i", - ret); + if ((ret = (*Mod_Test)(&mod->modinfo)) < MOD_SUCCESS) + { + ircsnprintf(errorbuf, sizeof(errorbuf), "Mod_Test returned %i", ret); /* We EXPECT the module to have cleaned up its mess */ Module_free(mod); return (errorbuf); } } mod->flags = MODFLAG_TESTING; - AddListItemPrio(mod, Modules, 0); return NULL; } else @@ -1221,7 +1222,7 @@ void ModuleSetOptions(Module *module, unsigned int options, int action) { unsigned int oldopts = module->options; - if (options == MOD_OPT_UNLOAD_PRIORITY) + if (options == MOD_OPT_PRIORITY) { DelListItem(module, Modules); AddListItemPrio(module, Modules, action); diff --git a/src/modules/channeldb.c b/src/modules/channeldb.c index 08d472539..4eb1a5a07 100644 --- a/src/modules/channeldb.c +++ b/src/modules/channeldb.c @@ -93,7 +93,7 @@ MOD_INIT() { MARK_AS_OFFICIAL_MODULE(modinfo); /* We must unload early, when all channel modes and such are still in place: */ - ModuleSetOptions(modinfo->handle, MOD_OPT_UNLOAD_PRIORITY, -99999999); + ModuleSetOptions(modinfo->handle, MOD_OPT_PRIORITY, -99999999); LoadPersistentLong(modinfo, channeldb_next_event); diff --git a/src/modules/history_backend_mem.c b/src/modules/history_backend_mem.c index a288c5609..ae2f1a7e8 100644 --- a/src/modules/history_backend_mem.c +++ b/src/modules/history_backend_mem.c @@ -132,7 +132,7 @@ MOD_INIT() MARK_AS_OFFICIAL_MODULE(modinfo); /* We must unload early, when all channel modes and such are still in place: */ - ModuleSetOptions(modinfo->handle, MOD_OPT_UNLOAD_PRIORITY, -99999999); + ModuleSetOptions(modinfo->handle, MOD_OPT_PRIORITY, -99999999); setcfg(&cfg); diff --git a/src/modules/rpc/rpc.c b/src/modules/rpc/rpc.c index 047e840bb..9793af798 100644 --- a/src/modules/rpc/rpc.c +++ b/src/modules/rpc/rpc.c @@ -70,6 +70,10 @@ MOD_TEST() EfunctionAddVoid(modinfo->handle, EFUNC_RPC_RESPONSE, _rpc_response); EfunctionAddVoid(modinfo->handle, EFUNC_RPC_ERROR, _rpc_error); EfunctionAddVoid(modinfo->handle, EFUNC_RPC_ERROR_FMT, TO_VOIDFUNC(_rpc_error_fmt)); + + /* Call MOD_INIT very early, since we manage sockets, but depend on websocket_common */ + ModuleSetOptions(modinfo->handle, MOD_OPT_PRIORITY, WEBSOCKET_MODULE_PRIORITY_INIT+1); + return MOD_SUCCESS; } @@ -79,17 +83,21 @@ MOD_INIT() MARK_AS_OFFICIAL_MODULE(modinfo); + websocket_md = findmoddata_byname("websocket", MODDATATYPE_CLIENT); /* can be NULL */ + HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN_EX, 0, rpc_config_run_ex_listen); HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, rpc_config_run_rpc_user); HookAdd(modinfo->handle, HOOKTYPE_HANDSHAKE, -5000, rpc_client_accept); HookAdd(modinfo->handle, HOOKTYPE_RAWPACKET_IN, INT_MIN, rpc_packet_in_unix_socket); + /* Call MOD_LOAD very late, since we manage sockets, but depend on websocket_common */ + ModuleSetOptions(modinfo->handle, MOD_OPT_PRIORITY, WEBSOCKET_MODULE_PRIORITY_UNLOAD-1); + return MOD_SUCCESS; } MOD_LOAD() { - websocket_md = findmoddata_byname("websocket", MODDATATYPE_CLIENT); /* can be NULL */ return MOD_SUCCESS; } diff --git a/src/modules/tkldb.c b/src/modules/tkldb.c index bfbefdc20..2316f0bba 100644 --- a/src/modules/tkldb.c +++ b/src/modules/tkldb.c @@ -128,7 +128,7 @@ MOD_TEST() MOD_INIT() { MARK_AS_OFFICIAL_MODULE(modinfo); - ModuleSetOptions(modinfo->handle, MOD_OPT_UNLOAD_PRIORITY, -9999); + ModuleSetOptions(modinfo->handle, MOD_OPT_PRIORITY, -9999); LoadPersistentLong(modinfo, tkldb_next_event); diff --git a/src/modules/websocket.c b/src/modules/websocket.c index fefddac7f..a639b9c02 100644 --- a/src/modules/websocket.c +++ b/src/modules/websocket.c @@ -64,6 +64,9 @@ MOD_TEST() { HookAdd(modinfo->handle, HOOKTYPE_CONFIGTEST, 0, websocket_config_test); HookAdd(modinfo->handle, HOOKTYPE_CONFIGPOSTTEST, 0, websocket_config_posttest); + + /* Call MOD_INIT very early, since we manage sockets, but depend on websocket_common */ + ModuleSetOptions(modinfo->handle, MOD_OPT_PRIORITY, WEBSOCKET_MODULE_PRIORITY_INIT+1); return MOD_SUCCESS; } @@ -73,18 +76,21 @@ MOD_INIT() MARK_AS_OFFICIAL_MODULE(modinfo); + websocket_md = findmoddata_byname("websocket", MODDATATYPE_CLIENT); + if (!websocket_md) + config_warn("The 'websocket_common' module is not loaded, even though it was promised to be ???"); + HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN_EX, 0, websocket_config_run_ex); HookAdd(modinfo->handle, HOOKTYPE_PACKET, INT_MAX, websocket_packet_out); HookAdd(modinfo->handle, HOOKTYPE_SECURE_CONNECT, 0, websocket_secure_connect); + /* Call MOD_LOAD very late, since we manage sockets, but depend on websocket_common */ + ModuleSetOptions(modinfo->handle, MOD_OPT_PRIORITY, WEBSOCKET_MODULE_PRIORITY_UNLOAD-1); return MOD_SUCCESS; } MOD_LOAD() { - websocket_md = findmoddata_byname("websocket", MODDATATYPE_CLIENT); - if (!websocket_md) - config_warn("The 'websocket_common' module is not loaded, even though it was promised to be ???"); if (non_utf8_nick_chars_in_use || (iConf.allowed_channelchars == ALLOWED_CHANNELCHARS_ANY)) ws_text_mode_available = 0; return MOD_SUCCESS; diff --git a/src/modules/websocket_common.c b/src/modules/websocket_common.c index 33f0a9509..1288149c7 100644 --- a/src/modules/websocket_common.c +++ b/src/modules/websocket_common.c @@ -58,6 +58,10 @@ MOD_TEST() EfunctionAdd(modinfo->handle, EFUNC_WEBSOCKET_HANDLE_WEBSOCKET, _websocket_handle_websocket); EfunctionAdd(modinfo->handle, EFUNC_WEBSOCKET_CREATE_PACKET, _websocket_create_packet); EfunctionAdd(modinfo->handle, EFUNC_WEBSOCKET_CREATE_PACKET_SIMPLE, _websocket_create_packet_simple); + + /* Init first, since we manage sockets */ + ModuleSetOptions(modinfo->handle, MOD_OPT_PRIORITY, WEBSOCKET_MODULE_PRIORITY_INIT); + return MOD_SUCCESS; } @@ -76,6 +80,9 @@ MOD_INIT() mreq.type = MODDATATYPE_CLIENT; websocket_md = ModDataAdd(modinfo->handle, mreq); + /* Unload last, since we manage sockets */ + ModuleSetOptions(modinfo->handle, MOD_OPT_PRIORITY, WEBSOCKET_MODULE_PRIORITY_UNLOAD); + return MOD_SUCCESS; }