Skip to content
This repository has been archived by the owner on Jun 24, 2021. It is now read-only.

Commit

Permalink
MODRESTART: Defer restart to the event loop
Browse files Browse the repository at this point in the history
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.

Return immediately from the command handler and have the event loop
call the function responsible for reloading the modules instead.

Reported-by: mniip (Freenode)
  • Loading branch information
aaronmdjones committed Dec 28, 2016
1 parent 9cdd727 commit db05a36
Showing 1 changed file with 26 additions and 14 deletions.
40 changes: 26 additions & 14 deletions src/modules.c
Original file line number Diff line number Diff line change
Expand Up @@ -463,21 +463,10 @@ mo_modlist(struct Client *client_p, struct Client *source_p, int parc, const cha
}

/* unload and reload all modules */
static int
mo_modrestart(struct Client *client_p, struct Client *source_p, int parc, const char **parv)
static void
modules_do_restart(void *unused)
{
int modnum;

if(!IsOperAdmin(source_p))
{
sendto_one(source_p, form_str(ERR_NOPRIVS),
me.name, source_p->name, "admin");
return 0;
}

sendto_one_notice(source_p, ":Reloading all modules");

modnum = num_mods;
int modnum = num_mods;
while (num_mods)
unload_one_module(modlist[0]->name, 0);

Expand All @@ -489,6 +478,29 @@ mo_modrestart(struct Client *client_p, struct Client *source_p, int parc, const
"Module Restart: %d modules unloaded, %d modules loaded",
modnum, num_mods);
ilog(L_MAIN, "Module Restart: %d modules unloaded, %d modules loaded", modnum, num_mods);
}

static int
mo_modrestart(struct Client *client_p, struct Client *source_p, int parc, const char **parv)
{
if(!IsOperAdmin(source_p))
{
sendto_one(source_p, form_str(ERR_NOPRIVS),
me.name, source_p->name, "admin");
return 0;
}

sendto_one_notice(source_p, ":Reloading all modules");

/*
* 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). This will go horribly wrong if m_encap is reloaded to
* a different address.
*
* So, defer the restart to the event loop (above) and return now.
*/
rb_event_addonce("modules_do_restart", modules_do_restart, NULL, 1);
return 0;
}

Expand Down

0 comments on commit db05a36

Please sign in to comment.