Skip to content

Commit 50e6e99

Browse files
authored
bpo-39984: Move pending calls to PyInterpreterState (GH-19066)
If Py_AddPendingCall() is called in a subinterpreter, the function is now scheduled to be called from the subinterpreter, rather than being called from the main interpreter. Each subinterpreter now has its own list of scheduled calls. * Move pending and eval_breaker fields from _PyRuntimeState.ceval to PyInterpreterState.ceval. * new_interpreter() now calls _PyEval_InitThreads() to create pending calls lock. * Fix Py_AddPendingCall() for subinterpreters. It now calls _PyThreadState_GET() which works in a subinterpreter if the caller holds the GIL, and only falls back on PyGILState_GetThisThreadState() if _PyThreadState_GET() returns NULL.
1 parent 3cde884 commit 50e6e99

File tree

8 files changed

+127
-82
lines changed

8 files changed

+127
-82
lines changed

Doc/c-api/init.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1389,6 +1389,10 @@ pointer and a void pointer argument.
13891389
This function doesn't need a current thread state to run, and it doesn't
13901390
need the global interpreter lock.
13911391
1392+
To call this function in a subinterpreter, the caller must hold the GIL.
1393+
Otherwise, the function *func* can be scheduled to be called from the wrong
1394+
interpreter.
1395+
13921396
.. warning::
13931397
This is a low-level function, only useful for very special cases.
13941398
There is no guarantee that *func* will be called as quick as
@@ -1397,6 +1401,12 @@ pointer and a void pointer argument.
13971401
function is generally **not** suitable for calling Python code from
13981402
arbitrary C threads. Instead, use the :ref:`PyGILState API<gilstate>`.
13991403
1404+
.. versionchanged:: 3.9
1405+
If this function is called in a subinterpreter, the function *func* is
1406+
now scheduled to be called from the subinterpreter, rather than being
1407+
called from the main interpreter. Each subinterpreter now has its own
1408+
list of scheduled calls.
1409+
14001410
.. versionadded:: 3.1
14011411
14021412
.. _profiling:

Doc/whatsnew/3.9.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,12 @@ Build and C API Changes
514514

515515
Extension modules without module state (``m_size <= 0``) are not affected.
516516

517+
* If :c:func:`Py_AddPendingCall` is called in a subinterpreter, the function is
518+
now scheduled to be called from the subinterpreter, rather than being called
519+
from the main interpreter. Each subinterpreter now has its own list of
520+
scheduled calls.
521+
(Contributed by Victor Stinner in :issue:`39984`.)
522+
517523

518524
Deprecated
519525
==========

Include/internal/pycore_pystate.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,8 @@ struct _pending_calls {
3535

3636
struct _ceval_runtime_state {
3737
int recursion_limit;
38-
/* This single variable consolidates all requests to break out of
39-
the fast path in the eval loop. */
40-
_Py_atomic_int eval_breaker;
4138
/* Request for dropping the GIL */
4239
_Py_atomic_int gil_drop_request;
43-
struct _pending_calls pending;
4440
/* Request for checking signals. */
4541
_Py_atomic_int signals_pending;
4642
struct _gil_runtime_state gil;
@@ -53,6 +49,10 @@ struct _ceval_state {
5349
c_tracefunc. This speeds up the if statement in
5450
_PyEval_EvalFrameDefault() after fast_next_opcode. */
5551
int tracing_possible;
52+
/* This single variable consolidates all requests to break out of
53+
the fast path in the eval loop. */
54+
_Py_atomic_int eval_breaker;
55+
struct _pending_calls pending;
5656
};
5757

5858
/* interpreter state */
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
If :c:func:`Py_AddPendingCall` is called in a subinterpreter, the function is
2+
now scheduled to be called from the subinterpreter, rather than being called
3+
from the main interpreter. Each subinterpreter now has its own list of
4+
scheduled calls.

Modules/signalmodule.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ trip_signal(int sig_num)
304304
if (wakeup.warn_on_full_buffer ||
305305
last_error != WSAEWOULDBLOCK)
306306
{
307-
/* Py_AddPendingCall() isn't signal-safe, but we
307+
/* _PyEval_AddPendingCall() isn't signal-safe, but we
308308
still use it for this exceptional case. */
309309
_PyEval_AddPendingCall(tstate,
310310
report_wakeup_send_error,
@@ -323,7 +323,7 @@ trip_signal(int sig_num)
323323
if (wakeup.warn_on_full_buffer ||
324324
(errno != EWOULDBLOCK && errno != EAGAIN))
325325
{
326-
/* Py_AddPendingCall() isn't signal-safe, but we
326+
/* _PyEval_AddPendingCall() isn't signal-safe, but we
327327
still use it for this exceptional case. */
328328
_PyEval_AddPendingCall(tstate,
329329
report_wakeup_write_error,

0 commit comments

Comments
 (0)