mirror of https://github.com/python/cpython
GH-118095: Make sure that progress is made if there are pending calls being handled. (GH-118484)
This commit is contained in:
parent
8a50544a99
commit
39981fd07a
|
@ -41,7 +41,7 @@ struct _pending_call {
|
|||
#define MAXPENDINGCALLSLOOP_MAIN 0
|
||||
|
||||
struct _pending_calls {
|
||||
int busy;
|
||||
PyThreadState *handling_thread;
|
||||
PyMutex mutex;
|
||||
/* Request for running pending calls. */
|
||||
int32_t npending;
|
||||
|
|
|
@ -877,21 +877,20 @@ make_pending_calls(PyThreadState *tstate)
|
|||
/* Only one thread (per interpreter) may run the pending calls
|
||||
at once. In the same way, we don't do recursive pending calls. */
|
||||
PyMutex_Lock(&pending->mutex);
|
||||
if (pending->busy) {
|
||||
if (pending->handling_thread != NULL) {
|
||||
/* A pending call was added after another thread was already
|
||||
handling the pending calls (and had already "unsignaled").
|
||||
Once that thread is done, it may have taken care of all the
|
||||
pending calls, or there might be some still waiting.
|
||||
Regardless, this interpreter's pending calls will stay
|
||||
"signaled" until that first thread has finished. At that
|
||||
point the next thread to trip the eval breaker will take
|
||||
care of any remaining pending calls. Until then, though,
|
||||
all the interpreter's threads will be tripping the eval
|
||||
breaker every time it's checked. */
|
||||
To avoid all threads constantly stopping on the eval breaker,
|
||||
we clear the bit for this thread and make sure it is set
|
||||
for the thread currently handling the pending call. */
|
||||
_Py_set_eval_breaker_bit(pending->handling_thread, _PY_CALLS_TO_DO_BIT);
|
||||
_Py_unset_eval_breaker_bit(tstate, _PY_CALLS_TO_DO_BIT);
|
||||
PyMutex_Unlock(&pending->mutex);
|
||||
return 0;
|
||||
}
|
||||
pending->busy = 1;
|
||||
pending->handling_thread = tstate;
|
||||
PyMutex_Unlock(&pending->mutex);
|
||||
|
||||
/* unsignal before starting to call callbacks, so that any callback
|
||||
|
@ -900,7 +899,7 @@ make_pending_calls(PyThreadState *tstate)
|
|||
|
||||
int32_t npending;
|
||||
if (_make_pending_calls(pending, &npending) != 0) {
|
||||
pending->busy = 0;
|
||||
pending->handling_thread = NULL;
|
||||
/* There might not be more calls to make, but we play it safe. */
|
||||
signal_pending_calls(tstate, interp);
|
||||
return -1;
|
||||
|
@ -912,7 +911,7 @@ make_pending_calls(PyThreadState *tstate)
|
|||
|
||||
if (_Py_IsMainThread() && _Py_IsMainInterpreter(interp)) {
|
||||
if (_make_pending_calls(pending_main, &npending) != 0) {
|
||||
pending->busy = 0;
|
||||
pending->handling_thread = NULL;
|
||||
/* There might not be more calls to make, but we play it safe. */
|
||||
signal_pending_calls(tstate, interp);
|
||||
return -1;
|
||||
|
@ -923,7 +922,7 @@ make_pending_calls(PyThreadState *tstate)
|
|||
}
|
||||
}
|
||||
|
||||
pending->busy = 0;
|
||||
pending->handling_thread = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue