aboutsummaryrefslogtreecommitdiffstats
path: root/lang/python/helpers.c
diff options
context:
space:
mode:
authorJustus Winter <[email protected]>2016-05-27 10:25:59 +0000
committerJustus Winter <[email protected]>2016-05-27 10:25:59 +0000
commitebfe2300c33a3bad311e9ac1530e6c92636a08a4 (patch)
treefa0eadc62b574c5838664eb93c3dadc879ace5b1 /lang/python/helpers.c
parentImprove comments. (diff)
downloadgpgme-ebfe2300c33a3bad311e9ac1530e6c92636a08a4.tar.gz
gpgme-ebfe2300c33a3bad311e9ac1530e6c92636a08a4.zip
python: Fix object deallocation.
Handing a reference to the wrapper object created a non-trivial circular reference that Pythons garbage collector is unable to break. Explicitly break it by using a weak reference. * lang/python/helpers.c (pygpgme_stash_callback_exception): Retrieve object from weak reference. * lang/python/pyme/core.py (Context.__del__): Free status callback. (Context.set_passphrase_cb): Use a weak reference. (Context.set_progress_cb): Likewise. (Context.set_status_cb): Likewise. (Context.op_edit): Likewise. Signed-off-by: Justus Winter <[email protected]>
Diffstat (limited to 'lang/python/helpers.c')
-rw-r--r--lang/python/helpers.c22
1 files changed, 19 insertions, 3 deletions
diff --git a/lang/python/helpers.c b/lang/python/helpers.c
index ec7264aa..9fe81c9f 100644
--- a/lang/python/helpers.c
+++ b/lang/python/helpers.c
@@ -64,9 +64,9 @@ void pygpgme_clear_generic_cb(PyObject **cb) {
/* Exception support for callbacks. */
#define EXCINFO "_callback_excinfo"
-static void pygpgme_stash_callback_exception(PyObject *self)
+static void pygpgme_stash_callback_exception(PyObject *weak_self)
{
- PyObject *ptype, *pvalue, *ptraceback, *excinfo;
+ PyObject *self, *ptype, *pvalue, *ptraceback, *excinfo;
PyErr_Fetch(&ptype, &pvalue, &ptraceback);
excinfo = PyTuple_New(3);
@@ -86,7 +86,23 @@ static void pygpgme_stash_callback_exception(PyObject *self)
PyTuple_SetItem(excinfo, 2, Py_None);
}
- PyObject_SetAttrString(self, EXCINFO, excinfo);
+ self = PyWeakref_GetObject(weak_self);
+ /* self only has a borrowed reference. */
+ if (self == Py_None) {
+ /* This should not happen, as even if we're called from the data
+ release callback triggered from the wrappers destructor, the
+ object is still alive and hence the weak reference still refers
+ to the object. However, in case this ever changes, not seeing
+ any exceptions is worse than having a little extra code, so
+ here we go. */
+ fprintf(stderr,
+ "Error occurred in callback, but the wrapper object "
+ "has been deallocated.\n");
+ PyErr_Restore(ptype, pvalue, ptraceback);
+ PyErr_Print();
+ }
+ else
+ PyObject_SetAttrString(self, EXCINFO, excinfo);
}
PyObject *pygpgme_raise_callback_exception(PyObject *self)