diff --git a/src/greenlet/greenlet.c b/src/greenlet/greenlet.c index eeece049..e299ed09 100644 --- a/src/greenlet/greenlet.c +++ b/src/greenlet/greenlet.c @@ -100,10 +100,13 @@ extern PyTypeObject PyGreenlet_Type; /* Python 3.10 beta 1 changed tstate->use_tracing to a nested cframe member. See https://github.com/python/cpython/pull/25276 +We have to save and restore this as well. */ #define TSTATE_USE_TRACING(tstate) (tstate->cframe->use_tracing) +#define GREENLET_USE_CFRAME 1 #else #define TSTATE_USE_TRACING(tstate) (tstate->use_tracing) +#define GREENLET_USE_CFRAME 0 #endif #ifndef Py_SET_REFCNT @@ -514,6 +517,9 @@ g_switchstack(void) current->exc_type = tstate->exc_type; current->exc_value = tstate->exc_value; current->exc_traceback = tstate->exc_traceback; +#endif +#if GREENLET_USE_CFRAME + current->cframe = tstate->cframe; #endif } err = slp_switch(); @@ -558,6 +564,10 @@ g_switchstack(void) #endif green_clear_exc(target); +#if GREENLET_USE_CFRAME + tstate->cframe = target->cframe; +#endif + assert(ts_origin == NULL); Py_INCREF(target); ts_current = target; @@ -907,6 +917,9 @@ green_new(PyTypeObject* type, PyObject* args, PyObject* kwds) } Py_INCREF(ts_current); ((PyGreenlet*)o)->parent = ts_current; +#if GREENLET_USE_CFRAME + ((PyGreenlet*)o)->cframe = &PyThreadState_GET()->root_cframe; +#endif } return o; } @@ -1611,8 +1624,9 @@ PyGreenlet_SetParent(PyGreenlet* g, PyGreenlet* nparent) static PyGreenlet* PyGreenlet_New(PyObject* run, PyGreenlet* parent) { + /* XXX: Why doesn't this call green_new()? There's some duplicate + code. */ PyGreenlet* g = NULL; - g = (PyGreenlet*)PyType_GenericAlloc(&PyGreenlet_Type, 0); if (g == NULL) { return NULL; @@ -1635,7 +1649,9 @@ PyGreenlet_New(PyObject* run, PyGreenlet* parent) return NULL; } } - +#if GREENLET_USE_CFRAME + g->cframe = &PyThreadState_GET()->root_cframe; +#endif return g; } diff --git a/src/greenlet/greenlet.h b/src/greenlet/greenlet.h index 13977821..830bef8d 100644 --- a/src/greenlet/greenlet.h +++ b/src/greenlet/greenlet.h @@ -38,6 +38,9 @@ typedef struct _greenlet { #if PY_VERSION_HEX >= 0x030700A3 PyObject* context; #endif +#if PY_VERSION_HEX >= 0x30A00B1 + CFrame* cframe; +#endif } PyGreenlet; #define PyGreenlet_Check(op) PyObject_TypeCheck(op, &PyGreenlet_Type) diff --git a/src/greenlet/tests/test_extension_interface.py b/src/greenlet/tests/test_extension_interface.py index bc874521..a92ea1f5 100644 --- a/src/greenlet/tests/test_extension_interface.py +++ b/src/greenlet/tests/test_extension_interface.py @@ -72,3 +72,6 @@ def foo(): str(seen[0]), 'take that sucka!', "message doesn't match") + +if __name__ == '__main__': + unittest.main()