Skip to content

Commit 8fd495b

Browse files
committed
PyUnstable_InterpreterState_SetEvalFrameFunc() can now fail
1 parent c624f74 commit 8fd495b

File tree

7 files changed

+44
-16
lines changed

7 files changed

+44
-16
lines changed

Doc/c-api/init.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1470,6 +1470,8 @@ All of the following functions must be called after :c:func:`Py_Initialize`.
14701470
14711471
Set the frame evaluation function.
14721472
1473+
Return ``0`` on success, or set an exception and return ``-1`` on error.
1474+
14731475
See the :pep:`523` "Adding a frame evaluation API to CPython".
14741476
14751477
.. versionadded:: next

Include/cpython/pystate.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ typedef PyObject* (*PyUnstable_FrameEvalFunction)(PyThreadState *tstate, struct
306306

307307
PyAPI_FUNC(PyUnstable_FrameEvalFunction) PyUnstable_InterpreterState_GetEvalFrameFunc(
308308
PyInterpreterState *interp);
309-
PyAPI_FUNC(void) PyUnstable_InterpreterState_SetEvalFrameFunc(
309+
PyAPI_FUNC(int) PyUnstable_InterpreterState_SetEvalFrameFunc(
310310
PyInterpreterState *interp,
311311
PyUnstable_FrameEvalFunction eval_frame);
312312

Modules/_testcapimodule.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2606,13 +2606,16 @@ test_interpreter_setevalframefunc(PyObject *self, PyObject *Py_UNUSED(args))
26062606
{
26072607
PyInterpreterState *interp = PyInterpreterState_Get();
26082608
PyUnstable_FrameEvalFunction eval_func;
2609+
int res;
26092610

26102611
eval_func = PyUnstable_InterpreterState_GetEvalFrameFunc(interp);
26112612

2612-
PyUnstable_InterpreterState_SetEvalFrameFunc(interp, noop_eval);
2613+
res = PyUnstable_InterpreterState_SetEvalFrameFunc(interp, noop_eval);
2614+
assert(res == 0);
26132615
assert(PyUnstable_InterpreterState_GetEvalFrameFunc(interp) == noop_eval);
26142616

2615-
PyUnstable_InterpreterState_SetEvalFrameFunc(interp, eval_func);
2617+
res = PyUnstable_InterpreterState_SetEvalFrameFunc(interp, eval_func);
2618+
assert(res == 0);
26162619

26172620
Py_RETURN_NONE;
26182621
}

Modules/_testinternalcapi.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -656,9 +656,12 @@ decode_locale_ex(PyObject *self, PyObject *args)
656656
static PyObject *
657657
set_eval_frame_default(PyObject *self, PyObject *Py_UNUSED(args))
658658
{
659+
PyInterpreterState *interp = _PyInterpreterState_GET();
660+
PyUnstable_FrameEvalFunction eval_func = _PyEval_EvalFrameDefault;
661+
if (PyUnstable_InterpreterState_SetEvalFrameFunc(interp, eval_func) < 0) {
662+
return NULL;
663+
}
659664
module_state *state = get_module_state(self);
660-
PyUnstable_InterpreterState_SetEvalFrameFunc(_PyInterpreterState_GET(),
661-
_PyEval_EvalFrameDefault);
662665
Py_CLEAR(state->record_list);
663666
Py_RETURN_NONE;
664667
}
@@ -690,8 +693,10 @@ set_eval_frame_record(PyObject *self, PyObject *list)
690693
return NULL;
691694
}
692695
Py_XSETREF(state->record_list, Py_NewRef(list));
693-
PyUnstable_InterpreterState_SetEvalFrameFunc(_PyInterpreterState_GET(),
694-
record_eval);
696+
PyInterpreterState *interp = _PyInterpreterState_GET();
697+
if (PyUnstable_InterpreterState_SetEvalFrameFunc(interp, record_eval) < 0) {
698+
return NULL;
699+
}
695700
Py_RETURN_NONE;
696701
}
697702

Python/perf_trampoline.c

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,9 @@ _PyPerfTrampoline_SetCallbacks(_PyPerf_Callbacks *callbacks)
470470
}
471471
#ifdef PY_HAVE_PERF_TRAMPOLINE
472472
if (trampoline_api.state) {
473-
_PyPerfTrampoline_Fini();
473+
if (_PyPerfTrampoline_Fini() < 0) {
474+
return -1;
475+
}
474476
}
475477
trampoline_api.init_state = callbacks->init_state;
476478
trampoline_api.write_state = callbacks->write_state;
@@ -486,12 +488,18 @@ _PyPerfTrampoline_Init(int activate)
486488
#ifdef PY_HAVE_PERF_TRAMPOLINE
487489
PyThreadState *tstate = _PyThreadState_GET();
488490
if (!activate) {
489-
PyUnstable_InterpreterState_SetEvalFrameFunc(tstate->interp, prev_eval_frame);
491+
if (PyUnstable_InterpreterState_SetEvalFrameFunc(tstate->interp,
492+
prev_eval_frame) < 0) {
493+
return -1;
494+
}
490495
perf_status = PERF_STATUS_NO_INIT;
491496
}
492497
else if (tstate->interp->eval_frame != py_trampoline_evaluator) {
493498
prev_eval_frame = PyUnstable_InterpreterState_GetEvalFrameFunc(tstate->interp);
494-
PyUnstable_InterpreterState_SetEvalFrameFunc(tstate->interp, py_trampoline_evaluator);
499+
if (PyUnstable_InterpreterState_SetEvalFrameFunc(tstate->interp,
500+
py_trampoline_evaluator) < 0) {
501+
return -1;
502+
}
495503
extra_code_index = _PyEval_RequestCodeExtraIndex(NULL);
496504
if (extra_code_index == -1) {
497505
return -1;
@@ -517,7 +525,9 @@ _PyPerfTrampoline_Fini(void)
517525
}
518526
PyThreadState *tstate = _PyThreadState_GET();
519527
if (tstate->interp->eval_frame == py_trampoline_evaluator) {
520-
PyUnstable_InterpreterState_SetEvalFrameFunc(tstate->interp, NULL);
528+
if (PyUnstable_InterpreterState_SetEvalFrameFunc(tstate->interp, NULL) < 0) {
529+
return -1;
530+
}
521531
}
522532
if (perf_status == PERF_STATUS_OK) {
523533
trampoline_api.free_state(trampoline_api.state);
@@ -553,7 +563,9 @@ _PyPerfTrampoline_AfterFork_Child(void)
553563
if (perf_trampoline_type != PERF_TRAMPOLINE_TYPE_MAP) {
554564
return PyStatus_Error("Failed to copy perf map file as perf trampoline type is not type map.");
555565
}
556-
_PyPerfTrampoline_Fini();
566+
if (_PyPerfTrampoline_Fini() < 0) {
567+
return PyStatus_Error("_PyPerfTrampoline_Fini() failed");
568+
}
557569
char filename[256];
558570
pid_t parent_pid = getppid();
559571
snprintf(filename, sizeof(filename), "/tmp/perf-%d.map", parent_pid);
@@ -563,7 +575,9 @@ _PyPerfTrampoline_AfterFork_Child(void)
563575
} else {
564576
// Restart trampoline in file in child.
565577
int was_active = _PyIsPerfTrampolineActive();
566-
_PyPerfTrampoline_Fini();
578+
if (_PyPerfTrampoline_Fini() < 0) {
579+
return PyStatus_Error("_PyPerfTrampoline_Fini() failed");
580+
}
567581
if (was_active) {
568582
_PyPerfTrampoline_Init(1);
569583
}

Python/pylifecycle.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1940,7 +1940,10 @@ finalize_interp_clear(PyThreadState *tstate)
19401940
_Py_HashRandomization_Fini();
19411941
_PyArg_Fini();
19421942
_Py_ClearFileSystemEncoding();
1943-
_PyPerfTrampoline_Fini();
1943+
if (_PyPerfTrampoline_Fini() < 0) {
1944+
PyErr_FormatUnraisable("Exception ignored on "
1945+
"_PyPerfTrampoline_Fini()");
1946+
}
19441947
_PyPerfTrampoline_FreeArenas();
19451948
}
19461949

Python/pystate.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2906,15 +2906,15 @@ PyUnstable_InterpreterState_GetEvalFrameFunc(PyInterpreterState *interp)
29062906
}
29072907

29082908

2909-
void
2909+
int
29102910
PyUnstable_InterpreterState_SetEvalFrameFunc(PyInterpreterState *interp,
29112911
PyUnstable_FrameEvalFunction eval_frame)
29122912
{
29132913
if (eval_frame == _PyEval_EvalFrameDefault) {
29142914
eval_frame = NULL;
29152915
}
29162916
if (eval_frame == interp->eval_frame) {
2917-
return;
2917+
return 0;
29182918
}
29192919
#ifdef _Py_TIER2
29202920
if (eval_frame != NULL) {
@@ -2925,6 +2925,7 @@ PyUnstable_InterpreterState_SetEvalFrameFunc(PyInterpreterState *interp,
29252925
_PyEval_StopTheWorld(interp);
29262926
interp->eval_frame = eval_frame;
29272927
_PyEval_StartTheWorld(interp);
2928+
return 0;
29282929
}
29292930

29302931

0 commit comments

Comments
 (0)