Skip to content

Commit

Permalink
merge 3.3-slp (Stackless python#117, exception handling)
Browse files Browse the repository at this point in the history
  • Loading branch information
Anselm Kruis committed Mar 17, 2017
2 parents 33080ce + 0ad0eac commit 230c713
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 6 deletions.
3 changes: 3 additions & 0 deletions Stackless/changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ What's New in Stackless 3.X.X?
- https://bitbucket.org/stackless-dev/stackless/issues/117
Fix various reference leaks:
- Leak of a reference to Py_None in generator.throw()

Additionally this change brings the handling of caught exceptions more in
line with C-Python.

- https://bitbucket.org/stackless-dev/stackless/issues/111
Restore the Python ABI function PyGen_New(). Previously Stackless named this
Expand Down
51 changes: 45 additions & 6 deletions Stackless/module/scheduling.c
Original file line number Diff line number Diff line change
Expand Up @@ -553,14 +553,31 @@ kill_wrap_bad_guy(PyTaskletObject *prev, PyTaskletObject *bad_guy)
PyObject *
slp_restore_exception(PyFrameObject *f, int exc, PyObject *retval)
{
PyObject *tmp_type, *tmp_value, *tmp_tb;
PyThreadState *ts = PyThreadState_GET();
PyCFrameObject *cf = (PyCFrameObject *) f;

if (cf->ob1 == NULL) {
/* set_exc_info in ceval.c contains the same assertions */
assert(cf->ob2 == NULL);
assert(cf->ob3 == NULL);
}

f = cf->f_back;
/* Set new exception for this thread.
* This code is follows suit the code of set_exc_info() in ceval.c */
tmp_type = ts->exc_type;
tmp_value = ts->exc_value;
tmp_tb = ts->exc_traceback;
ts->exc_type = cf->ob1;
ts->exc_value = cf->ob2;
ts->exc_traceback = cf->ob3;
cf->ob1 = cf->ob2 = cf->ob3 = NULL;

Py_XDECREF(tmp_type);
Py_XDECREF(tmp_value);
Py_XDECREF(tmp_tb);

Py_DECREF(cf);
ts->frame = f;
return STACKLESS_PACK(ts, retval);
Expand Down Expand Up @@ -1071,17 +1088,32 @@ slp_schedule_task_prepared(PyThreadState *ts, PyObject **result, PyTaskletObject
}
if (ts->exc_type != NULL) {
/* build a shadow frame if we are returning here*/
/* The following code follows suit the code of sys.exc_clear() and
* ceval.c set_exc_info()
*/
if (ts->frame != NULL) {
PyCFrameObject *f = slp_cframe_new(slp_restore_exception, 1);
if (f == NULL)
return -1;
f->ob1 = ts->exc_type;
f->ob2 = ts->exc_value;
f->ob3 = ts->exc_traceback;
ts->exc_type = NULL;
ts->exc_value = NULL;
ts->exc_traceback = NULL;
prev->f.frame = (PyFrameObject *) f;
} else {
PyObject *tmp_type, *tmp_value, *tmp_tb;
tmp_type = ts->exc_type;
tmp_value = ts->exc_value;
tmp_tb = ts->exc_traceback;
ts->exc_type = NULL;
ts->exc_value = NULL;
ts->exc_traceback = NULL;
Py_XDECREF(tmp_type);
Py_XDECREF(tmp_value);
Py_XDECREF(tmp_tb);
}
ts->exc_type = ts->exc_value =
ts->exc_traceback = NULL;
}
if (ts->use_tracing || ts->tracing) {
/* build a shadow frame if we are returning here */
Expand Down Expand Up @@ -1425,12 +1457,19 @@ slp_tasklet_end(PyObject *retval)
* clean up any current exception - this tasklet is dead.
* This only happens if we are killing tasklets in the middle
* of their execution.
* The code follows suit the code of sys.exc_clear().
*/
if (ts->exc_type != NULL && ts->exc_type != Py_None) {
Py_DECREF(ts->exc_type);
Py_XDECREF(ts->exc_value);
Py_XDECREF(ts->exc_traceback);
ts->exc_type = ts->exc_value = ts->exc_traceback = NULL;
PyObject *tmp_type, *tmp_value, *tmp_tb;
tmp_type = ts->exc_type;
tmp_value = ts->exc_value;
tmp_tb = ts->exc_traceback;
ts->exc_type = NULL;
ts->exc_value = NULL;
ts->exc_traceback = NULL;
Py_DECREF(tmp_type);
Py_XDECREF(tmp_value);
Py_XDECREF(tmp_tb);
}

/* capture all exceptions */
Expand Down

0 comments on commit 230c713

Please sign in to comment.