diff --git a/moulinette/actionsmap.py b/moulinette/actionsmap.py index 4458fd44..9d35c24e 100644 --- a/moulinette/actionsmap.py +++ b/moulinette/actionsmap.py @@ -526,6 +526,18 @@ class ActionsMap(object): logger.debug('action [%s] executed in %.3fs', log_id, stop - start) + # For some reason we need to do this now before the + # garbage collector kicks in ... + # ... because sometimes the ldap library is already half + # gone when trying to properly close the ldap object + # which leads to : + # TypeError: "'NoneType' object is not callable" in > ignored + # (here the NoneType stuff refers to RequestControlTuples in ldapobject.py ...) + # I got this when running `yunohost user list` (but not when running `yunohost domain list` for some reason) + from moulinette.authenticators.ldap import Authenticator + for i in Authenticator.instances: + i().freecon() + @staticmethod def get_namespaces(): """ diff --git a/moulinette/authenticators/ldap.py b/moulinette/authenticators/ldap.py index f3625efc..fe83dab9 100644 --- a/moulinette/authenticators/ldap.py +++ b/moulinette/authenticators/ldap.py @@ -9,6 +9,7 @@ import crypt import ldap import ldap.sasl import ldap.modlist as modlist +import weakref from moulinette.core import MoulinetteError from moulinette.authenticators import BaseAuthenticator @@ -33,11 +34,13 @@ class Authenticator(BaseAuthenticator): """ + instances = [] def __init__(self, name, uri, base_dn, user_rdn=None): logger.debug("initialize authenticator '%s' with: uri='%s', " "base_dn='%s', user_rdn='%s'", name, uri, base_dn, user_rdn) super(Authenticator, self).__init__(name) + self.__class__.instances.append(weakref.proxy(self)) self.uri = uri self.basedn = base_dn if user_rdn: @@ -52,10 +55,14 @@ class Authenticator(BaseAuthenticator): self.authenticate(None) def __del__(self): + self.freecon() + + def freecon(self): """Disconnect and free ressources""" - if self.con: + if self.con and hasattr(self.con, "_l"): self.con.unbind_s() + # Implement virtual properties vendor = 'ldap'