From b0b5f8442d67354fd1781bd55c0f8c4fe30553e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benno=20F=C3=BCnfst=C3=BCck?= Date: Fri, 15 Sep 2017 17:21:25 +0200 Subject: [PATCH] python: Fix exception in finalizer at exit (#873) Sometimes, the finalizer for an `UcRef` runs so late that the members of the module have already been set to `None`. We need to make sure that we don't depend on anything in the module, or we risk getting a Exception when we try to access the `release_handle` method of `None` (`Uc`). --- bindings/python/unicorn/unicorn.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/bindings/python/unicorn/unicorn.py b/bindings/python/unicorn/unicorn.py index de7a6135..a394138c 100644 --- a/bindings/python/unicorn/unicorn.py +++ b/bindings/python/unicorn/unicorn.py @@ -251,11 +251,26 @@ class UcCleanupManager(object): def register(self, uc): ref = UcRef(uc, self._finalizer) ref._uch = uc._uch + ref._class = uc.__class__ self._refs[id(ref)] = ref def _finalizer(self, ref): + # note: this method must be completely self-contained and cannot have any references + # to anything else in this module. + # + # This is because it may be called late in the Python interpreter's shutdown phase, at + # which point the module's variables may already have been deinitialized and set to None. + # + # Not respecting that can lead to errors such as: + # Exception AttributeError: + # "'NoneType' object has no attribute 'release_handle'" + # in > ignored + # + # For that reason, we do not try to access the `Uc` class directly here but instead use + # the saved `._class` reference. del self._refs[id(ref)] - Uc.release_handle(ref._uch) + ref._class.release_handle(ref._uch) class Uc(object): _cleanup = UcCleanupManager()