From c8a4668bbffa37af2314de1cd2a7ca694b6e7ded Mon Sep 17 00:00:00 2001 From: Alexey Sokolov Date: Sun, 1 Jan 2012 16:46:21 +0700 Subject: [PATCH] Unload all python modules when modpython is unloaded. Only user modules were unloaded before. --- modules/modpython.cpp | 31 +++++++++---------------------- modules/modpython/znc.py | 15 ++++++++++++--- 2 files changed, 21 insertions(+), 25 deletions(-) diff --git a/modules/modpython.cpp b/modules/modpython.cpp index e86a966a..4c65a8a7 100644 --- a/modules/modpython.cpp +++ b/modules/modpython.cpp @@ -320,28 +320,15 @@ public: } virtual ~CModPython() { - const map& users = CZNC::Get().GetUserMap(); - for (map::const_iterator i = users.begin(); i != users.end(); ++i) { - CModules& M = i->second->GetModules(); - bool cont; - do { - cont = false; - for (CModules::iterator it = M.begin(); it != M.end(); ++it) { - CModule* m = *it; - CPyModule* mod = AsPyModule(m); - if (mod) { - cont = true; - bool bSuccess = false; - CString sRetMsg; - OnModuleUnloading(mod, bSuccess, sRetMsg); - if (!bSuccess) { - DEBUG("Error unloading python module in ~CModPython: " << sRetMsg); - } - break; - } - } - } while (cont); - } + PyObject* pyFunc = PyObject_GetAttrString(m_PyZNCModule, "unload_all"); + PyObject* pyRes = PyObject_CallFunctionObjArgs(pyFunc, NULL); + if (!pyRes) { + CString sRetMsg = GetPyExceptionStr(); + DEBUG("modpython tried to unload all modules in its destructor, but: " << sRetMsg); + } + Py_CLEAR(pyRes); + Py_CLEAR(pyFunc); + Py_CLEAR(m_PyFormatException); Py_CLEAR(m_PyZNCModule); Py_Finalize(); diff --git a/modules/modpython/znc.py b/modules/modpython/znc.py index 50bebd20..6a924140 100644 --- a/modules/modpython/znc.py +++ b/modules/modpython/znc.py @@ -423,6 +423,7 @@ def find_open(modname): # nothing found return (None, None) +_py_modules = set() def load_module(modname, args, module_type, user, network, retmsg, modpython): '''Returns 0 if not found, 1 on loading error, 2 on success''' @@ -450,23 +451,24 @@ def load_module(modname, args, module_type, user, network, retmsg, modpython): module.SetArgs(args) module.SetModPath(pymodule.__file__) module.SetType(module_type) + _py_modules.add(module) if module_type == CModInfo.UserModule: if not user: - retmsg.s = "Module [modpython] needs user for for UserModule." + retmsg.s = "Module [{}] is UserModule and needs user.".format(modname) unload_module(module) return 1 user.GetModules().push_back(module._cmod) elif module_type == CModInfo.NetworkModule: if not network: - retmsg.s = "Module [modpython] needs a network for for NetworkModule." + retmsg.s = "Module [{}] is Network module and needs a network.".format(modname) unload_module(module) return 1 network.GetModules().push_back(module._cmod) elif module_type == CModInfo.GlobalModule: CZNC.Get().GetModules().push_back(module._cmod) else: - retmsg.s = "Module [modpython] doesn't support module type." + retmsg.s = "Module [{}] doesn't support that module type.".format(modname) unload_module(module) return 1 @@ -508,6 +510,7 @@ def load_module(modname, args, module_type, user, network, retmsg, modpython): def unload_module(module): module.OnShutdown() + _py_modules.discard(module) cmod = module._cmod if module.GetType() == CModInfo.UserModule: cmod.GetUser().GetModules().removeModule(cmod) @@ -520,6 +523,12 @@ def unload_module(module): del cmod +def unload_all(): + while len(_py_modules) > 0: + mod = _py_modules.pop() + unload_module(mod) + + def get_mod_info(modname, retmsg, modinfo): '''0-not found, 1-error, 2-success''' pymodule, datadir = find_open(modname)