Skip to content

Commit

Permalink
Save/restore exceptions in green_updatecurrent
Browse files Browse the repository at this point in the history
There's a slim chance that PyDict_SetItem or
PyDict_DelItem might clobber exceptions during
lookups, so they need to be preserved.
  • Loading branch information
snaury committed Jun 3, 2012
1 parent ee4d8eb commit 98fb1a8
Showing 1 changed file with 20 additions and 4 deletions.
24 changes: 20 additions & 4 deletions greenlet.c
Expand Up @@ -207,39 +207,55 @@ static PyGreenlet* green_create_main(void)

static int green_updatecurrent(void)
{
PyObject *exc, *val, *tb;
PyThreadState* tstate;
PyGreenlet* next;
PyGreenlet* previous;
PyObject* deleteme;

/* save current exception */
PyErr_Fetch(&exc, &val, &tb);

/* save ts_current as the current greenlet of its own thread */
previous = ts_current;
if (PyDict_SetItem(previous->run_info, ts_curkey, (PyObject*) previous))
if (PyDict_SetItem(previous->run_info, ts_curkey, (PyObject*) previous)) {
Py_XDECREF(exc);
Py_XDECREF(val);
Py_XDECREF(tb);
return -1;
}

/* get ts_current from the active tstate */
tstate = PyThreadState_GET();
if (tstate->dict && (next =
(PyGreenlet*) PyDict_GetItem(tstate->dict, ts_curkey))) {
/* found -- remove it, to avoid keeping a ref */
Py_INCREF(next);
if (PyDict_DelItem(tstate->dict, ts_curkey) < 0)
PyErr_WriteUnraisable(ts_curkey);
PyDict_DelItem(tstate->dict, ts_curkey);
}
else {
/* first time we see this tstate */
next = green_create_main();
if (next == NULL)
if (next == NULL) {
Py_XDECREF(exc);
Py_XDECREF(val);
Py_XDECREF(tb);
return -1;
}
}
ts_current = next;
Py_DECREF(previous);

/* green_dealloc() cannot delete greenlets from other threads, so
it stores them in the thread dict; delete them now. */
deleteme = PyDict_GetItem(tstate->dict, ts_delkey);
if (deleteme != NULL) {
PyList_SetSlice(deleteme, 0, INT_MAX, NULL);
}

/* restore current exception */
PyErr_Restore(exc, val, tb);

return 0;
}

Expand Down

0 comments on commit 98fb1a8

Please sign in to comment.