Skip to content
This repository was archived by the owner on Feb 13, 2025. It is now read-only.

Commit 6fa9bf3

Browse files
author
Anselm Kruis
committed
Stackless issue #300: correctly call audit hooks "sys.settrace" and "sys.setprofile"
- Don't call the audit hooks when switching tasklets. - Add calls to tasklet_set_trace_function(), tasklet_set_profile_function() and tasklet_setstate().
1 parent daf50a8 commit 6fa9bf3

File tree

6 files changed

+61
-7
lines changed

6 files changed

+61
-7
lines changed

Doc/library/stackless/tasklets.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,12 @@ The ``tasklet`` class
444444
the :class:`~contextvars.Context` object of the
445445
tasklet to the :class:`~contextvars.Context` object of the current tasklet.
446446

447+
.. versionchanged:: 3.8
448+
449+
If the state contains a trace- or profile-function :meth:`~__setstate__` now
450+
raises an auditing event ``sys.settrace`` resp. ``sys.setprofile`` with
451+
no arguments.
452+
447453
:param state: the state as given by ``__reduce_ex__(...)[2]``
448454
:type state: :class:`tuple`
449455
:return: self
@@ -572,6 +578,11 @@ and thus may not be available in all |SLP| implementations.
572578
are the tasklet counterparts of the functions :func:`sys.settrace`,
573579
:func:`sys.gettrace`, :func:`sys.setprofile` and :func:`sys.getprofile`.
574580

581+
.. versionchanged:: 3.8
582+
583+
Assignments to these attributes now raise an auditing event
584+
``sys.settrace`` resp. ``sys.setprofile`` with no arguments.
585+
575586

576587
^^^^^^^^^^^^^^^^^^
577588
Tasklet Life Cycle

Include/internal/pycore_stackless.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -736,9 +736,11 @@ PyObject * slp_async_gen_athrow_new(PyAsyncGenObject *gen);
736736
PyObject * slp_async_gen_athrow_setstate(PyObject *self, PyObject *args);
737737

738738
/* debugging/monitoring */
739-
740739
int slp_schedule_callback(PyTaskletObject *prev, PyTaskletObject *next);
740+
void slp_set_profile(Py_tracefunc func, PyObject *arg);
741+
void slp_set_trace(Py_tracefunc func, PyObject *arg);
741742

743+
/* Stackless extension for types */
742744
int slp_prepare_slots(PyTypeObject*);
743745

744746
Py_tracefunc slp_get_sys_profile_func(void);

Python/ceval.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5253,7 +5253,14 @@ PyEval_SetProfile(Py_tracefunc func, PyObject *arg)
52535253
if (PySys_Audit("sys.setprofile", NULL) < 0) {
52545254
return;
52555255
}
5256+
#ifdef STACKLESS
5257+
slp_set_profile(func, arg);
5258+
}
52565259

5260+
void
5261+
slp_set_profile(Py_tracefunc func, PyObject *arg)
5262+
{
5263+
#endif
52575264
PyThreadState *tstate = _PyThreadState_GET();
52585265
PyObject *temp = tstate->c_profileobj;
52595266
Py_XINCREF(arg);
@@ -5274,6 +5281,14 @@ PyEval_SetTrace(Py_tracefunc func, PyObject *arg)
52745281
if (PySys_Audit("sys.settrace", NULL) < 0) {
52755282
return;
52765283
}
5284+
#ifdef STACKLESS
5285+
slp_set_trace(func, arg);
5286+
}
5287+
5288+
void
5289+
slp_set_trace(Py_tracefunc func, PyObject *arg)
5290+
{
5291+
#endif
52775292

52785293
_PyRuntimeState *runtime = &_PyRuntime;
52795294
PyThreadState *tstate = _PyRuntimeState_GetThreadState(runtime);

Stackless/changelog.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@ What's New in Stackless 3.X.X?
99

1010
*Release date: 20XX-XX-XX*
1111

12+
- https://github.com/stackless-dev/stackless/issues/300
13+
Assignments to 'tasklet.trace_function', 'tasklet.profile_function' now raise
14+
an auditing event "sys.settrace" resp. "sys.setprofile" with no arguments.
15+
Unpickling a tasklet with trace- or profile-function now raises an
16+
auditing event "sys.settrace" resp. "sys.setprofile" with no arguments.
17+
1218
- https://github.com/stackless-dev/stackless/issues/275
1319
Add limited support for the eval_frame-hook introduced by PEP-523.
1420
Stackless can't fully support all use-cases. Currently the hook can be used

Stackless/module/scheduling.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -622,7 +622,7 @@ Py_LOCAL_INLINE(void) SLP_UPDATE_TSTATE_ON_SWITCH(PyThreadState *tstate, PyTaskl
622622
Py_XINCREF(prev->profileobj);
623623
if (prev->profileobj)
624624
assert(Py_REFCNT(prev->profileobj) >= 2); /* won't drop to zero in PyEval_SetProfile */
625-
PyEval_SetProfile(next->profilefunc, next->profileobj);
625+
slp_set_profile(next->profilefunc, next->profileobj);
626626
next->profilefunc = NULL;
627627
if (next->profileobj)
628628
assert(Py_REFCNT(next->profileobj) >= 2); /* won't drop to zero */
@@ -642,7 +642,7 @@ Py_LOCAL_INLINE(void) SLP_UPDATE_TSTATE_ON_SWITCH(PyThreadState *tstate, PyTaskl
642642
assert(Py_REFCNT(prev->traceobj) >= 2); /* won't drop to zero in PyEval_SetTrace */
643643
prev->tracing = tstate->tracing;
644644
tstate->tracing = next->tracing;
645-
PyEval_SetTrace(next->tracefunc, next->traceobj);
645+
slp_set_trace(next->tracefunc, next->traceobj);
646646
next->tracefunc = NULL;
647647
if (next->traceobj)
648648
assert(Py_REFCNT(next->traceobj) >= 2); /* won't drop to zero */
@@ -682,7 +682,7 @@ Py_LOCAL_INLINE(void) SLP_UPDATE_TSTATE_ON_SWITCH(PyThreadState *tstate, PyTaskl
682682
Py_XINCREF(prev__->profileobj); \
683683
if (prev__->profileobj) \
684684
assert(Py_REFCNT(prev__->profileobj) >= 2); /* won't drop to zero in PyEval_SetProfile */ \
685-
PyEval_SetProfile(next__->profilefunc, next__->profileobj); \
685+
slp_set_profile(next__->profilefunc, next__->profileobj); \
686686
next__->profilefunc = NULL; \
687687
if (next__->profileobj) \
688688
assert(Py_REFCNT(next__->profileobj) >= 2); /* won't drop to zero */ \
@@ -701,7 +701,7 @@ Py_LOCAL_INLINE(void) SLP_UPDATE_TSTATE_ON_SWITCH(PyThreadState *tstate, PyTaskl
701701
assert(Py_REFCNT(prev__->traceobj) >= 2); /* won't drop to zero in PyEval_SetTrace */ \
702702
prev__->tracing = ts__->tracing; \
703703
ts__->tracing = next__->tracing; \
704-
PyEval_SetTrace(next__->tracefunc, next__->traceobj); \
704+
slp_set_trace(next__->tracefunc, next__->traceobj); \
705705
next__->tracefunc = NULL; \
706706
if (next__->traceobj) \
707707
assert(Py_REFCNT(next__->traceobj) >= 2); /* won't drop to zero */ \

Stackless/module/taskletobject.c

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -853,6 +853,20 @@ tasklet_setstate(PyObject *self, PyObject *args)
853853
}
854854

855855
/* profile and tracing */
856+
if ((c_functions & 1) || (Py_None != traceobj)) {
857+
/* trace setting requested */
858+
if (PySys_Audit("sys.settrace", NULL)) {
859+
return NULL;
860+
}
861+
}
862+
863+
if ((c_functions & 2) || (Py_None != profileobj)) {
864+
/* profile setting requested */
865+
if (PySys_Audit("sys.setprofile", NULL)) {
866+
return NULL;
867+
}
868+
}
869+
856870
if (c_functions & 1) {
857871
Py_tracefunc func = slp_get_sys_trace_func();
858872
if (NULL == func)
@@ -2141,6 +2155,9 @@ tasklet_set_trace_function(PyTaskletObject *task, PyObject *value, void *closure
21412155
PyThreadState *ts = task->cstate->tstate;
21422156
Py_tracefunc tf = NULL;
21432157

2158+
if (PySys_Audit("sys.settrace", NULL)) {
2159+
return -1;
2160+
}
21442161
if (Py_None == value)
21452162
value = NULL;
21462163
if (value) {
@@ -2152,7 +2169,7 @@ tasklet_set_trace_function(PyTaskletObject *task, PyObject *value, void *closure
21522169
/* current tasklet */
21532170
if (_PyThreadState_GET() != ts)
21542171
RUNTIME_ERROR("You cannot set the trace function of the current tasklet of another thread", -1);
2155-
PyEval_SetTrace(tf, value);
2172+
slp_set_trace(tf, value);
21562173
return 0;
21572174
}
21582175

@@ -2182,6 +2199,9 @@ tasklet_set_profile_function(PyTaskletObject *task, PyObject *value, void *closu
21822199
PyThreadState *ts = task->cstate->tstate;
21832200
Py_tracefunc tf = NULL;
21842201

2202+
if (PySys_Audit("sys.setprofile", NULL)) {
2203+
return -1;
2204+
}
21852205
if (Py_None == value)
21862206
value = NULL;
21872207
if (value) {
@@ -2193,7 +2213,7 @@ tasklet_set_profile_function(PyTaskletObject *task, PyObject *value, void *closu
21932213
/* current tasklet */
21942214
if (_PyThreadState_GET() != ts)
21952215
RUNTIME_ERROR("You cannot set the profile function of the current tasklet of another thread", -1);
2196-
PyEval_SetProfile(tf, value);
2216+
slp_set_profile(tf, value);
21972217
return 0;
21982218
}
21992219

0 commit comments

Comments
 (0)