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) | 
