Skip to content

Commit

Permalink
Stackless issue python#177: Fix prickelpit.c function slp_cannot_exec…
Browse files Browse the repository at this point in the history
…ute()

I missed the C-fame case, when I changed the frame-function ref counting
in Stackless issue python#117.
  • Loading branch information
Anselm Kruis authored and Anselm Kruis committed Oct 31, 2018
1 parent e7a3769 commit 5a574b8
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 20 deletions.
18 changes: 18 additions & 0 deletions Include/frameobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,24 @@ extern "C" {

#ifdef STACKLESS
typedef PyObject *(PyFrame_ExecFunc) (struct _frame *, int, PyObject *);
/*
* How to write frame execution functions:
*
* Special rule for frame execution functions: the function owns a reference to retval!
*
* PyObject * example(PyFrameObject *f, int exc, PyObject *retval)
* {
* PyThreadState *ts = PyThreadState_GET();
*
* do something ....
* if you change retval, use Py_SETREF(retval, new_value) or
* Py_CLEAR(retval)
*
* SLP_STORE_NEXT_FRAME(ts, f->f_back);
* return retval;
* }
*
*/
#endif

typedef struct {
Expand Down
6 changes: 6 additions & 0 deletions Stackless/changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ What's New in Stackless 3.X.X?

*Release date: 20XX-XX-XX*

- https://github.com/stackless-dev/stackless/issues/177
Fix a crasher in prickelpit.c slp_cannot_execute().
Stackless versions released after March 2017 can crash, if a program executes
an unpickled tasklet, that lost its C-state. Now Stackless always raises
RuntimeError.

- https://github.com/stackless-dev/stackless/issues/152
C-Python bpo30860 consolidates stateful C globals under a single struct.
Stackless also moves its stateful C globals to the appropriate structures
Expand Down
38 changes: 19 additions & 19 deletions Stackless/pickling/prickelpit.c
Original file line number Diff line number Diff line change
Expand Up @@ -365,34 +365,34 @@ run_script(char *src, char *retname)
*/

PyObject *
slp_cannot_execute(PyFrameObject *f, char *exec_name, PyObject *retval)
slp_cannot_execute(PyFrameObject *f, const char *exec_name, PyObject *retval)
{
/*
* Special rule for frame execution functions: we now own a reference to retval!
*/

/*
* show an error message and raise exception.
*/
PyObject *message;
PyThreadState *tstate = PyThreadState_GET();

/* if we already have an exception, we keep it */
if (retval == NULL)
goto err_exit;

message = PyUnicode_FromFormat("cannot execute invalid frame with "
"'%.100s': frame had a C state that"
" can't be restored.",
exec_name);
if (message == NULL) {
/* try at least something */
PyErr_SetString(PyExc_RuntimeError,
"invalid frame, cannot build error message.");
goto err_exit;
if (retval != NULL) {
Py_DECREF(retval);
PyErr_Format(PyExc_RuntimeError, "cannot execute invalid frame with "
"'%.100s': frame had a C state that"
" can't be restored.",
exec_name);
}
PyErr_SetObject(PyExc_RuntimeError, message);
Py_DECREF(message);
err_exit:

SLP_STORE_NEXT_FRAME(tstate, f->f_back);
--tstate->recursion_depth;
Py_XDECREF(retval);

if(PyFrame_Check(f)) {
/* Only real frames contribute to the recursion count.
* C-frames don't contribute, see tasklet_setstate(...) */
--tstate->recursion_depth;
}

return NULL;
}

Expand Down
2 changes: 1 addition & 1 deletion Stackless/pickling/prickelpit.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ int slp_find_execfuncs(PyTypeObject *type, PyObject *exec_name,

PyObject * slp_find_execname(PyFrameObject *f, int *valid);

PyObject * slp_cannot_execute(PyFrameObject *f, char *exec_name, PyObject *retval);
PyObject * slp_cannot_execute(PyFrameObject *f, const char *exec_name, PyObject *retval);

/* macros to define and use an invalid frame executor */

Expand Down

0 comments on commit 5a574b8

Please sign in to comment.