From f9c1b779670422cde44d111403990d1031e91eb3 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Mon, 20 Sep 2021 12:25:11 +0100 Subject: [PATCH 1/2] Add tstate.use_tracing as a copy of tstate.cframe->use_tracing to minimize breakage in Cython generated modules. --- Include/cpython/pystate.h | 1 + Python/ceval.c | 25 ++++++++++++++----------- Python/pystate.c | 1 + Python/sysmodule.c | 10 ++++++---- 4 files changed, 22 insertions(+), 15 deletions(-) diff --git a/Include/cpython/pystate.h b/Include/cpython/pystate.h index e3ccc543560849..064ad3162f6631 100644 --- a/Include/cpython/pystate.h +++ b/Include/cpython/pystate.h @@ -76,6 +76,7 @@ struct _ts { This is to prevent the actual trace/profile code from being recorded in the trace/profile. */ int tracing; + int use_tracing; /* Pointer to current CFrame in the C stack frame of the currently, * or most recently, executing _PyEval_EvalFrameDefault. */ diff --git a/Python/ceval.c b/Python/ceval.c index 429ddb82bd66d4..83af22bdb38a17 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -5476,7 +5476,7 @@ call_trace(Py_tracefunc func, PyObject *obj, if (tstate->tracing) return 0; tstate->tracing++; - tstate->cframe->use_tracing = 0; + tstate->use_tracing = tstate->cframe->use_tracing = 0; if (frame->f_lasti < 0) { frame->f_lineno = frame->f_code->co_firstlineno; } @@ -5486,8 +5486,8 @@ call_trace(Py_tracefunc func, PyObject *obj, } result = func(obj, frame, what, arg); frame->f_lineno = 0; - tstate->cframe->use_tracing = ((tstate->c_tracefunc != NULL) - || (tstate->c_profilefunc != NULL)); + tstate->use_tracing = tstate->cframe->use_tracing = + ((tstate->c_tracefunc != NULL) || (tstate->c_profilefunc != NULL)); tstate->tracing--; return result; } @@ -5501,11 +5501,11 @@ _PyEval_CallTracing(PyObject *func, PyObject *args) PyObject *result; tstate->tracing = 0; - tstate->cframe->use_tracing = ((tstate->c_tracefunc != NULL) - || (tstate->c_profilefunc != NULL)); + tstate->use_tracing = tstate->cframe->use_tracing = + ((tstate->c_tracefunc != NULL) || (tstate->c_profilefunc != NULL)); result = PyObject_Call(func, args, NULL); tstate->tracing = save_tracing; - tstate->cframe->use_tracing = save_use_tracing; + tstate->use_tracing = tstate->cframe->use_tracing = save_use_tracing; return result; } @@ -5556,7 +5556,8 @@ _PyEval_SetProfile(PyThreadState *tstate, Py_tracefunc func, PyObject *arg) tstate->c_profilefunc = NULL; tstate->c_profileobj = NULL; /* Must make sure that tracing is not ignored if 'profileobj' is freed */ - tstate->cframe->use_tracing = tstate->c_tracefunc != NULL; + tstate->use_tracing = tstate->cframe->use_tracing = + tstate->c_tracefunc != NULL; Py_XDECREF(profileobj); Py_XINCREF(arg); @@ -5564,7 +5565,8 @@ _PyEval_SetProfile(PyThreadState *tstate, Py_tracefunc func, PyObject *arg) tstate->c_profilefunc = func; /* Flag that tracing or profiling is turned on */ - tstate->cframe->use_tracing = (func != NULL) || (tstate->c_tracefunc != NULL); + tstate->use_tracing = tstate->cframe->use_tracing = + (func != NULL) || (tstate->c_tracefunc != NULL); return 0; } @@ -5597,7 +5599,8 @@ _PyEval_SetTrace(PyThreadState *tstate, Py_tracefunc func, PyObject *arg) tstate->c_tracefunc = NULL; tstate->c_traceobj = NULL; /* Must make sure that profiling is not ignored if 'traceobj' is freed */ - tstate->cframe->use_tracing = (tstate->c_profilefunc != NULL); + tstate->use_tracing = tstate->cframe->use_tracing = + (tstate->c_profilefunc != NULL); Py_XDECREF(traceobj); Py_XINCREF(arg); @@ -5605,8 +5608,8 @@ _PyEval_SetTrace(PyThreadState *tstate, Py_tracefunc func, PyObject *arg) tstate->c_tracefunc = func; /* Flag that tracing or profiling is turned on */ - tstate->cframe->use_tracing = ((func != NULL) - || (tstate->c_profilefunc != NULL)); + tstate->use_tracing = tstate->cframe->use_tracing = + ((func != NULL) || (tstate->c_profilefunc != NULL)); return 0; } diff --git a/Python/pystate.c b/Python/pystate.c index aeebd6f61c6d7f..556851f4374787 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -623,6 +623,7 @@ new_threadstate(PyInterpreterState *interp, int init) tstate->recursion_headroom = 0; tstate->stackcheck_counter = 0; tstate->tracing = 0; + tstate->use_tracing = 0; tstate->root_cframe.use_tracing = 0; tstate->cframe = &tstate->root_cframe; tstate->gilstate_counter = 0; diff --git a/Python/sysmodule.c b/Python/sysmodule.c index ac49f7867a5cb3..b9ed6ff04145c0 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -253,7 +253,7 @@ sys_audit_tstate(PyThreadState *ts, const char *event, /* Disallow tracing in hooks unless explicitly enabled */ ts->tracing++; - ts->cframe->use_tracing = 0; + ts->use_tracing = ts->cframe->use_tracing = 0; while ((hook = PyIter_Next(hooks)) != NULL) { _Py_IDENTIFIER(__cantrace__); PyObject *o; @@ -266,14 +266,15 @@ sys_audit_tstate(PyThreadState *ts, const char *event, break; } if (canTrace) { - ts->cframe->use_tracing = (ts->c_tracefunc || ts->c_profilefunc); + ts->use_tracing = ts->cframe->use_tracing = + (ts->c_tracefunc || ts->c_profilefunc); ts->tracing--; } PyObject* args[2] = {eventName, eventArgs}; o = _PyObject_FastCallTstate(ts, hook, args, 2); if (canTrace) { ts->tracing++; - ts->cframe->use_tracing = 0; + ts->use_tracing = ts->cframe->use_tracing = 0; } if (!o) { break; @@ -281,7 +282,8 @@ sys_audit_tstate(PyThreadState *ts, const char *event, Py_DECREF(o); Py_CLEAR(hook); } - ts->cframe->use_tracing = (ts->c_tracefunc || ts->c_profilefunc); + ts->use_tracing = ts->cframe->use_tracing = + (ts->c_tracefunc || ts->c_profilefunc); ts->tracing--; if (_PyErr_Occurred(ts)) { goto exit; From 6eb2c126db2e0ba9e489b04581d033c7962b0d67 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Tue, 21 Sep 2021 11:01:52 +0100 Subject: [PATCH 2/2] Move new field to end of struct for better binary compatibility. --- Include/cpython/pystate.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Include/cpython/pystate.h b/Include/cpython/pystate.h index 064ad3162f6631..c10ba5f0108bae 100644 --- a/Include/cpython/pystate.h +++ b/Include/cpython/pystate.h @@ -76,7 +76,6 @@ struct _ts { This is to prevent the actual trace/profile code from being recorded in the trace/profile. */ int tracing; - int use_tracing; /* Pointer to current CFrame in the C stack frame of the currently, * or most recently, executing _PyEval_EvalFrameDefault. */ @@ -149,6 +148,7 @@ struct _ts { uint64_t id; CFrame root_cframe; + int use_tracing; /* XXX signal handlers should also be here */