pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/python/cpython/commit/757b402ea1c2c6b925a55a08fd844b065b6e082f

gh-104812: Run Pending Calls in any Thread (gh-104813) · python/cpython@757b402 · GitHub
Skip to content

Commit 757b402

Browse files
gh-104812: Run Pending Calls in any Thread (gh-104813)
For a while now, pending calls only run in the main thread (in the main interpreter). This PR changes things to allow any thread run a pending call, unless the pending call was explicitly added for the main thread to run.
1 parent 4e80082 commit 757b402

16 files changed

Lines changed: 761 additions & 118 deletions

File tree

Include/cpython/ceval.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ PyAPI_FUNC(PyObject *) _PyEval_EvalFrameDefault(PyThreadState *tstate, struct _P
2222
PyAPI_FUNC(void) _PyEval_SetSwitchInterval(unsigned long microseconds);
2323
PyAPI_FUNC(unsigned long) _PyEval_GetSwitchInterval(void);
2424

25+
PyAPI_FUNC(int) _PyEval_MakePendingCalls(PyThreadState *);
26+
2527
PyAPI_FUNC(Py_ssize_t) PyUnstable_Eval_RequestCodeExtraIndex(freefunc);
2628
// Old name -- remove when this API changes:
2729
_Py_DEPRECATED_EXTERNALLY(3.12) static inline Py_ssize_t

Include/internal/pycore_ceval.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ PyAPI_FUNC(void) _PyEval_SignalReceived(PyInterpreterState *interp);
2727
PyAPI_FUNC(int) _PyEval_AddPendingCall(
2828
PyInterpreterState *interp,
2929
int (*func)(void *),
30-
void *arg);
30+
void *arg,
31+
int mainthreadonly);
3132
PyAPI_FUNC(void) _PyEval_SignalAsyncExc(PyInterpreterState *interp);
3233
#ifdef HAVE_FORK
3334
extern PyStatus _PyEval_ReInitThreads(PyThreadState *tstate);

Include/internal/pycore_ceval_state.h

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,24 @@ extern "C" {
1313
#include "pycore_gil.h" // struct _gil_runtime_state
1414

1515

16+
struct _pending_calls {
17+
int busy;
18+
PyThread_type_lock lock;
19+
/* Request for running pending calls. */
20+
_Py_atomic_int calls_to_do;
21+
/* Request for looking at the `async_exc` field of the current
22+
thread state.
23+
Guarded by the GIL. */
24+
int async_exc;
25+
#define NPENDINGCALLS 32
26+
struct _pending_call {
27+
int (*func)(void *);
28+
void *arg;
29+
} calls[NPENDINGCALLS];
30+
int first;
31+
int last;
32+
};
33+
1634
typedef enum {
1735
PERF_STATUS_FAILED = -1, // Perf trampoline is in an invalid state
1836
PERF_STATUS_NO_INIT = 0, // Perf trampoline is not initialized
@@ -49,6 +67,8 @@ struct _ceval_runtime_state {
4967
the main thread of the main interpreter can handle signals: see
5068
_Py_ThreadCanHandleSignals(). */
5169
_Py_atomic_int signals_pending;
70+
/* Pending calls to be made only on the main thread. */
71+
struct _pending_calls pending_mainthread;
5272
};
5373

5474
#ifdef PY_HAVE_PERF_TRAMPOLINE
@@ -62,24 +82,6 @@ struct _ceval_runtime_state {
6282
#endif
6383

6484

65-
struct _pending_calls {
66-
int busy;
67-
PyThread_type_lock lock;
68-
/* Request for running pending calls. */
69-
_Py_atomic_int calls_to_do;
70-
/* Request for looking at the `async_exc` field of the current
71-
thread state.
72-
Guarded by the GIL. */
73-
int async_exc;
74-
#define NPENDINGCALLS 32
75-
struct {
76-
int (*func)(void *);
77-
void *arg;
78-
} calls[NPENDINGCALLS];
79-
int first;
80-
int last;
81-
};
82-
8385
struct _ceval_state {
8486
/* This single variable consolidates all requests to break out of
8587
the fast path in the eval loop. */

Include/internal/pycore_pystate.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,6 @@ _Py_ThreadCanHandleSignals(PyInterpreterState *interp)
6060
}
6161

6262

63-
/* Only execute pending calls on the main thread. */
64-
static inline int
65-
_Py_ThreadCanHandlePendingCalls(void)
66-
{
67-
return _Py_IsMainThread();
68-
}
69-
70-
7163
/* Variable and static inline functions for in-line access to current thread
7264
and interpreter state */
7365

Lib/test/support/threading_helper.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,11 @@ def join_thread(thread, timeout=None):
115115

116116
@contextlib.contextmanager
117117
def start_threads(threads, unlock=None):
118-
import faulthandler
118+
try:
119+
import faulthandler
120+
except ImportError:
121+
# It isn't supported on subinterpreters yet.
122+
faulthandler = None
119123
threads = list(threads)
120124
started = []
121125
try:
@@ -147,7 +151,8 @@ def start_threads(threads, unlock=None):
147151
finally:
148152
started = [t for t in started if t.is_alive()]
149153
if started:
150-
faulthandler.dump_traceback(sys.stdout)
154+
if faulthandler is not None:
155+
faulthandler.dump_traceback(sys.stdout)
151156
raise AssertionError('Unable to join %d threads' % len(started))
152157

153158

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy