When a remote MODRESTART command is received, it will pass through the
ENCAP module. The ms_encap function is responsible for dispatching the
command handler and then the modules will eventually be reloaded.
However, if the ENCAP module is reloaded to a different address, the
stack now contains the address of a function that no longer exists.
Also, in this version of the IRCd, the module restarting functionality
was located in a function that is itself located in a module, so things
will also go badly if that module is reloaded to a different address,
too.
Return immediately from the command handler and have the event loop
call the function responsible for reloading the modules instead.
c.f. release/3.5 commit db05a36210
Reported-by: mniip (Freenode)
This commit is contained in:
parent
6002ccec6b
commit
41390bfe5f
2 changed files with 48 additions and 30 deletions
|
@ -668,3 +668,38 @@ load_a_module(const char *path, bool warn, int origin, bool core)
|
|||
rb_free(mod_displayname);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
modules_do_restart(void *unused)
|
||||
{
|
||||
unsigned int modnum = 0;
|
||||
rb_dlink_node *ptr, *nptr;
|
||||
|
||||
RB_DLINK_FOREACH_SAFE(ptr, nptr, module_list.head)
|
||||
{
|
||||
struct module *mod = ptr->data;
|
||||
if(!unload_one_module(mod->name, false))
|
||||
{
|
||||
ilog(L_MAIN, "Module Restart: %s was not unloaded %s",
|
||||
mod->name,
|
||||
mod->core? "(core module)" : "");
|
||||
|
||||
if(!mod->core)
|
||||
sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
|
||||
"Module Restart: %s failed to unload",
|
||||
mod->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
modnum++;
|
||||
}
|
||||
|
||||
load_all_modules(false);
|
||||
load_core_modules(false);
|
||||
rehash(false);
|
||||
|
||||
sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
|
||||
"Module Restart: %u modules unloaded, %lu modules loaded",
|
||||
modnum, rb_dlink_list_length(&module_list));
|
||||
ilog(L_MAIN, "Module Restart: %u modules unloaded, %lu modules loaded", modnum, rb_dlink_list_length(&module_list));
|
||||
}
|
||||
|
|
|
@ -54,6 +54,8 @@ static void do_modreload(struct Client *, const char *);
|
|||
static void do_modlist(struct Client *, const char *);
|
||||
static void do_modrestart(struct Client *);
|
||||
|
||||
extern void modules_do_restart(void *); /* end of ircd/modules.c */
|
||||
|
||||
struct Message modload_msgtab = {
|
||||
"MODLOAD", 0, 0, 0, 0,
|
||||
{mg_unreg, mg_not_oper, mg_ignore, mg_ignore, {me_modload, 2}, {mo_modload, 2}}
|
||||
|
@ -341,38 +343,19 @@ do_modreload(struct Client *source_p, const char *module)
|
|||
static void
|
||||
do_modrestart(struct Client *source_p)
|
||||
{
|
||||
unsigned int modnum = 0;
|
||||
rb_dlink_node *ptr, *nptr;
|
||||
|
||||
sendto_one_notice(source_p, ":Reloading all modules");
|
||||
|
||||
RB_DLINK_FOREACH_SAFE(ptr, nptr, module_list.head)
|
||||
{
|
||||
struct module *mod = ptr->data;
|
||||
if(!unload_one_module(mod->name, false))
|
||||
{
|
||||
ilog(L_MAIN, "Module Restart: %s was not unloaded %s",
|
||||
mod->name,
|
||||
mod->core? "(core module)" : "");
|
||||
|
||||
if(!mod->core)
|
||||
sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
|
||||
"Module Restart: %s failed to unload",
|
||||
mod->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
modnum++;
|
||||
}
|
||||
|
||||
load_all_modules(false);
|
||||
load_core_modules(false);
|
||||
rehash(false);
|
||||
|
||||
sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
|
||||
"Module Restart: %u modules unloaded, %lu modules loaded",
|
||||
modnum, rb_dlink_list_length(&module_list));
|
||||
ilog(L_MAIN, "Module Restart: %u modules unloaded, %lu modules loaded", modnum, rb_dlink_list_length(&module_list));
|
||||
/*
|
||||
* If a remote MODRESTART is received, m_encap.so will be reloaded,
|
||||
* but ms_encap is in the call stack (it indirectly calls this
|
||||
* function). Also, this function is itself in a module.
|
||||
*
|
||||
* This will go horribly wrong if either module is reloaded to a
|
||||
* different address.
|
||||
*
|
||||
* So, defer the restart to the event loop and return now.
|
||||
*/
|
||||
rb_event_addonce("modules_do_restart", modules_do_restart, NULL, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
Loading…
Reference in a new issue