diff --git a/pym/portage/util/_ctypes.py b/pym/portage/util/_ctypes.py index f419b19..13ab6e5 100644 --- a/pym/portage/util/_ctypes.py +++ b/pym/portage/util/_ctypes.py @@ -1,9 +1,12 @@ # Copyright 2012 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 +from __future__ import absolute_import, print_function + try: import ctypes import ctypes.util + import _ctypes except ImportError: ctypes = None else: @@ -12,6 +15,10 @@ else: except AttributeError: ctypes = None +import traceback + +from portage.proxy.objectproxy import ObjectProxy + _library_names = {} def find_library(name): @@ -40,6 +47,36 @@ def LoadLibrary(name): handle = None if ctypes is not None: - handle = ctypes.cdll.LoadLibrary(name) + handle = _LibraryHandleProxy(ctypes.cdll.LoadLibrary(name)) return handle + +class _LibraryHandleProxy(ObjectProxy): + + __slots__ = ('_target',) + + def __init__(self, target): + object.__setattr__(self, '_target', target) + + def _get_target(self): + return object.__getattribute__(self, '_target') + + def __del__(self): + """ + Calls _ctypes.dlclose() for the proxied CDLL instance, since it + doesn't happen automatically (see http://bugs.python.org/issue14597). + """ + try: + _handle = object.__getattribute__(self, '_target')._handle + object.__delattr__(self, '_target') + _ctypes.dlclose(_handle) + except (SystemExit, KeyboardInterrupt): + raise + except Exception: + # Make some noise if this breaks in a future python version. + traceback.print_exc() + print("_LibraryHandleProxy __del__", _handle) + + base_destructor = getattr(ObjectProxy, '__del__', None) + if base_destructor is not None: + base_destructor(self)