1
0
mirror of https://github.com/unrealircd/unrealircd.git synced 2026-06-30 04:16:39 +02:00

Fix crash when unloading (not reloading) module that uses ModData (#4903).

This commit is contained in:
Bram Matthys
2017-03-22 10:51:29 +01:00
parent e6a02003f5
commit fcaa69157b
3 changed files with 57 additions and 15 deletions
+20 -9
View File
@@ -187,7 +187,9 @@ void unload_moddata_commit(ModDataInfo *md)
list_for_each_entry(acptr, &lclient_list, lclient_node)
{
if (md->free && moddata_client(acptr, md).ptr)
md->free(moddata_client(acptr, md).ptr);
{
md->free(&moddata_client(acptr, md));
}
memset(&moddata_client(acptr, md), 0, sizeof(ModData));
}
break;
@@ -198,7 +200,7 @@ void unload_moddata_commit(ModDataInfo *md)
for (chptr = channel; chptr; chptr=chptr->nextch)
{
if (md->free && moddata_channel(chptr, md).ptr)
md->free(moddata_channel(chptr, md).ptr);
md->free(&moddata_channel(chptr, md));
memset(&moddata_channel(chptr, md), 0, sizeof(ModData));
}
break;
@@ -212,7 +214,7 @@ void unload_moddata_commit(ModDataInfo *md)
for (m = chptr->members; m; m = m->next)
{
if (md->free && moddata_member(m, md).ptr)
md->free(moddata_member(m, md).ptr);
md->free(&moddata_member(m, md));
memset(&moddata_member(m, md), 0, sizeof(ModData));
}
}
@@ -229,7 +231,7 @@ void unload_moddata_commit(ModDataInfo *md)
for (m = acptr->user->channel; m; m = m->next)
{
if (md->free && moddata_membership(m, md).ptr)
md->free(moddata_membership(m, md).ptr);
md->free(&moddata_membership(m, md));
memset(&moddata_membership(m, md), 0, sizeof(ModData));
}
}
@@ -239,12 +241,12 @@ void unload_moddata_commit(ModDataInfo *md)
DelListItem(md, MDInfo);
MyFree(md->name);
MyFree(MDInfo);
MyFree(md);
}
void ModDataDel(ModDataInfo *md)
{
/* Delete the reference to us first */
if (md->owner)
{
ModuleObject *mdobj;
@@ -273,9 +275,8 @@ ModDataInfo *md, *md_next;
for (md = MDInfo; md; md = md_next)
{
md_next = md->next;
if (md->owner)
abort(); /* shouldn't happen */
unload_moddata_commit(md);
if (md->unloaded)
unload_moddata_commit(md);
}
}
@@ -290,6 +291,16 @@ ModDataInfo *md;
return NULL;
}
int module_has_moddata(Module *mod)
{
ModDataInfo *md;
for (md = MDInfo; md; md = md->next)
if (md->owner == mod)
return 1;
return 0;
}
/** Set ModData for client (via variable name, string value) */
int moddata_client_set(aClient *acptr, char *varname, char *value)
-3
View File
@@ -867,9 +867,6 @@ vFP Module_SymX(char *name, Module **mptr)
return NULL;
}
void module_loadall(void)
{
iFP fp;
+37 -3
View File
@@ -257,6 +257,7 @@ extern void charsys_reset_pretest(void);
int charsys_postconftest(void);
void charsys_finish(void);
int reloadable_perm_module_unloaded(void);
void special_delayed_unloading(void);
int ssl_tests(void);
@@ -1628,6 +1629,9 @@ int config_test_all(void)
{
return 0;
}
special_delayed_unloading();
return 1;
}
@@ -9598,6 +9602,7 @@ int rehash_internal(aClient *cptr, aClient *sptr, int sig)
unload_all_unused_snomasks();
unload_all_unused_umodes();
unload_all_unused_extcmodes();
// unload_all_unused_moddata(); -- this will crash
extcmodes_check_for_changes();
loop.ircd_rehashing = 0;
remote_rehash_client = NULL;
@@ -9996,9 +10001,9 @@ int ssl_tests(void)
*/
int reloadable_perm_module_unloaded(void)
{
Module *m, *m2;
extern Module *Modules;
int ret = 0;
Module *m, *m2;
extern Module *Modules;
int ret = 0;
for (m = Modules; m; m = m->next)
{
@@ -10019,5 +10024,34 @@ int ret = 0;
}
}
}
return ret;
}
extern int module_has_moddata(Module *mod);
/** Special hack for unloading modules with moddata */
void special_delayed_unloading(void)
{
Module *m, *m2;
extern Module *Modules;
for (m = Modules; m; m = m->next)
{
if ((m->flags & MODFLAG_LOADED) && module_has_moddata(m) && !(m->options & MOD_OPT_PERM) && !(m->options & MOD_OPT_PERM_RELOADABLE))
{
int found = 0;
for (m2 = Modules; m2; m2 = m2->next)
{
if ((m != m2) && !strcmp(m->header->name, m2->header->name))
found = 1;
}
if (!found)
{
config_warn("Delaying module unloading of '%s' due to moddata", m->header->name);
m->flags |= MODFLAG_DELAYED;
EventAddEx(NULL, "e_unload_module_delayed", 5, 1, e_unload_module_delayed, m->header->name);
}
}
}
}