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:
+20
-9
@@ -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)
|
||||
|
||||
@@ -867,9 +867,6 @@ vFP Module_SymX(char *name, Module **mptr)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void module_loadall(void)
|
||||
{
|
||||
iFP fp;
|
||||
|
||||
+37
-3
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user