diff options
author | Justus Winter <[email protected]> | 2016-05-27 10:25:59 +0000 |
---|---|---|
committer | Justus Winter <[email protected]> | 2016-05-27 10:25:59 +0000 |
commit | ebfe2300c33a3bad311e9ac1530e6c92636a08a4 (patch) | |
tree | fa0eadc62b574c5838664eb93c3dadc879ace5b1 /lang/python/helpers.c | |
parent | Improve comments. (diff) | |
download | gpgme-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.c | 22 |
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) |