diff options
-rw-r--r-- | Changes | 1 | ||||
-rw-r--r-- | include/modules.h | 11 | ||||
-rw-r--r-- | include/services.h | 10 | ||||
-rw-r--r-- | src/module.cpp | 6 | ||||
-rw-r--r-- | src/modulemanager.cpp | 40 |
5 files changed, 54 insertions, 14 deletions
@@ -6,3 +6,4 @@ Anope Version 1.9.0 10/12 F Move BotInfo and related methods into a class 11/01 F Move modules into a class 11/15 F Fixed ns resending of passcode issue +11/15 F Modules now delete themselves
\ No newline at end of file diff --git a/include/modules.h b/include/modules.h index c09b234c2..9e2889646 100644 --- a/include/modules.h +++ b/include/modules.h @@ -259,7 +259,7 @@ CoreExport class Module * @return returns MOD_ERR_OK on success */ int DelCommand(CommandHash * cmdTable[], const char *name); - + /** * Adds a timed callback for the current module. * This allows modules to request that anope executes one of there functions at a time in the future, without an event to trigger it @@ -272,7 +272,7 @@ CoreExport class Module * @see moduleDelCallBack **/ int AddCallback(const char *name, time_t when, int (*func) (int argc, char *argv[]), int argc, char **argv); - + /** * Allow modules to delete a timed callback by name. * @param name the name of the callback they wish to delete @@ -307,10 +307,15 @@ CoreExport class ModuleManager * @return MOD_ERR_OK on success, anything else on fail */ static int UnloadModule(Module *m, User * u); - + /** Run all pending module timer callbacks. */ static void RunCallbacks(); +private: + /** Call the module_delete function to safely delete the module + * @param m the module to delete + */ + static void DeleteModule(Module *m); }; diff --git a/include/services.h b/include/services.h index 70aaf0066..af5b524c5 100644 --- a/include/services.h +++ b/include/services.h @@ -202,16 +202,24 @@ extern int strncasecmp(const char *, const char *, size_t); break; \ } \ return TRUE; \ + } \ + extern "C" DllExport void *destroy_module(y *m) \ + { \ + delete m; \ } + #else #define MODULE_INIT(x, y) \ extern "C" DllExport Module *init_module(const std::string &modname, const std::string &creator) \ { \ return new y(x, creator); \ + } \ + extern "C" DllExport void destroy_module(y *m) \ + { \ + delete m; \ } #endif - /* Miscellaneous definitions. */ #include "defs.h" #include "slist.h" diff --git a/src/module.cpp b/src/module.cpp index d0929bfdd..de72c7f64 100644 --- a/src/module.cpp +++ b/src/module.cpp @@ -69,12 +69,6 @@ Module::~Module() remove(this->filename.c_str()); - if (this->handle) - { - if ((ano_modclose(this->handle)) != 0) - alog("%s", ano_moderr()); - } - int idx; CommandHash *current = NULL; EvtHookHash *ehcurrent = NULL; diff --git a/src/modulemanager.cpp b/src/modulemanager.cpp index c248817bc..4f478c946 100644 --- a/src/modulemanager.cpp +++ b/src/modulemanager.cpp @@ -93,7 +93,7 @@ static bool IsOneOfModuleTypeLoaded(MODType mt) int idx = 0; ModuleHash *current = NULL; int pmods = 0; - + for (idx = 0; idx != MAX_CMD_HASH; idx++) { for (current = MODULE_HASH[idx]; current; current = current->next) @@ -201,13 +201,13 @@ int ModuleManager::LoadModule(const std::string &modname, User * u) if (m->type == PROTOCOL && IsOneOfModuleTypeLoaded(PROTOCOL)) { - delete m; + DeleteModule(m); alog("You cannot load two protocol modules"); return MOD_STOP; } else if (m->type == ENCRYPTION && IsOneOfModuleTypeLoaded(ENCRYPTION)) { - delete m; + DeleteModule(m); alog("You cannot load two encryption modules"); return MOD_STOP; } @@ -245,6 +245,38 @@ int ModuleManager::UnloadModule(Module *m, User *u) notice_lang(s_OperServ, u, OPER_MODULE_UNLOADED, m->name.c_str()); } - delete m; + DeleteModule(m); return MOD_ERR_OK; } + +void ModuleManager::DeleteModule(Module *m) +{ + const char *err; + void (*destroy_func)(Module *m); + void *handle; + + if (!m || !m->handle) /* check m is least possibly valid */ + { + return; + } + + handle = m->handle; + + ano_modclearerr(); + destroy_func = (void(*)(Module *m))ano_modsym(m->handle, "destroy_module"); + if (destroy_func == NULL && (err = ano_moderr()) != NULL) + { + alog("No magical destroy function found, chancing delete..."); + delete m; /* we just have to change they haven't overwrote the delete operator then... */ + } + else + { + destroy_func(m); /* Let the module delete it self, just in case */ + } + + if (handle) + { + if ((ano_modclose(handle)) != 0) + alog("%s", ano_moderr()); + } +} |