diff --git a/modules/modpython/znc.py b/modules/modpython/znc.py index fcc927b6..87e254a8 100644 --- a/modules/modpython/znc.py +++ b/modules/modpython/znc.py @@ -14,6 +14,7 @@ # limitations under the License. # +from functools import wraps import imp import re import traceback @@ -709,6 +710,35 @@ CChan.GetNicks = CChan.GetNicks_ CZNC.GetUserMap = CZNC.GetUserMap_ +def FreeOwnership(func): + """ + Force release of python ownership of user object when adding it to znc + + This solves #462 + """ + @wraps(func) + def _wrap(self, obj, *args): + # Bypass if first argument is not an SWIG object (like base type str) + if not hasattr(obj, 'thisown'): + return func(self, obj, *args) + # Change ownership of C++ object from SWIG/python to ZNC core if function was successful + if func(self, obj, *args): + # .thisown is magic SWIG's attribute which makes it call C++ "delete" when python's garbage collector deletes python wrapper + obj.thisown = 0 + return True + else: + return False + return _wrap + +CZNC.AddListener = FreeOwnership(func=CZNC.AddListener) +CZNC.AddUser = FreeOwnership(func=CZNC.AddUser) +CZNC.AddNetworkToQueue = FreeOwnership(func=CZNC.AddNetworkToQueue) +CUser.AddNetwork = FreeOwnership(func=CUser.AddNetwork) +CIRCNetwork.AddChan = FreeOwnership(func=CIRCNetwork.AddChan) +CModule.AddSocket = FreeOwnership(func=CModule.AddSocket) +CModule.AddSubPage = FreeOwnership(func=CModule.AddSubPage) + + class ModulesIter(collections.Iterator): def __init__(self, cmod): self._cmod = cmod