bpo-35370: Add _PyEval_SetTrace() function (GH-18975)
* sys.settrace(), sys.setprofile() and _lsprof.Profiler.enable() now
properly report PySys_Audit() error if "sys.setprofile" or
"sys.settrace" audit event is denied.
* Add _PyEval_SetProfile() and _PyEval_SetTrace() function: similar
to PyEval_SetProfile() and PyEval_SetTrace() but take a tstate
parameter and return -1 on error.
* Add _PyObject_FastCallTstate() function.
diff --git a/Modules/_lsprof.c b/Modules/_lsprof.c
index 2718c61..7115fee 100644
--- a/Modules/_lsprof.c
+++ b/Modules/_lsprof.c
@@ -578,8 +578,9 @@
profiler_getstats(ProfilerObject *pObj, PyObject* noarg)
{
statscollector_t collect;
- if (pending_exception(pObj))
+ if (pending_exception(pObj)) {
return NULL;
+ }
if (!pObj->externalTimer || pObj->externalTimerUnit == 0.0) {
_PyTime_t onesec = _PyTime_FromSeconds(1);
collect.factor = (double)1 / onesec;
@@ -639,9 +640,15 @@
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ii:enable",
kwlist, &subcalls, &builtins))
return NULL;
- if (setSubcalls(self, subcalls) < 0 || setBuiltins(self, builtins) < 0)
+ if (setSubcalls(self, subcalls) < 0 || setBuiltins(self, builtins) < 0) {
return NULL;
- PyEval_SetProfile(profiler_callback, (PyObject*)self);
+ }
+
+ PyThreadState *tstate = PyThreadState_GET();
+ if (_PyEval_SetProfile(tstate, profiler_callback, (PyObject*)self) < 0) {
+ return NULL;
+ }
+
self->flags |= POF_ENABLED;
Py_RETURN_NONE;
}
@@ -671,11 +678,16 @@
static PyObject*
profiler_disable(ProfilerObject *self, PyObject* noarg)
{
- self->flags &= ~POF_ENABLED;
- PyEval_SetProfile(NULL, NULL);
- flush_unmatched(self);
- if (pending_exception(self))
+ PyThreadState *tstate = PyThreadState_GET();
+ if (_PyEval_SetProfile(tstate, NULL, NULL) < 0) {
return NULL;
+ }
+ self->flags &= ~POF_ENABLED;
+
+ flush_unmatched(self);
+ if (pending_exception(self)) {
+ return NULL;
+ }
Py_RETURN_NONE;
}
@@ -695,8 +707,13 @@
static void
profiler_dealloc(ProfilerObject *op)
{
- if (op->flags & POF_ENABLED)
- PyEval_SetProfile(NULL, NULL);
+ if (op->flags & POF_ENABLED) {
+ PyThreadState *tstate = PyThreadState_GET();
+ if (_PyEval_SetProfile(tstate, NULL, NULL) < 0) {
+ PyErr_WriteUnraisable((PyObject *)op);
+ }
+ }
+
flush_unmatched(op);
clearEntries(op);
Py_XDECREF(op->externalTimer);