mirror of
https://github.com/python/cpython.git
synced 2025-07-07 19:35:27 +00:00
gh-135099: Only wait on _PyOS_SigintEvent()
in main thread (GH-135100)
On Windows, the `_PyOS_SigintEvent()` event handle is used to interrupt the main thread when Ctrl-C is pressed. Previously, we also waited on the event from other threads, but ignored the result. However, this can race with interpreter shutdown because the main thread closes the handle in `_PySignal_Fini` and threads may still be running and using mutexes during interpreter shtudown. Only use `_PyOS_SigintEvent()` in the main thread in parking_lot.c, like we do in other places in the CPython codebase.
This commit is contained in:
parent
8f778f7bb9
commit
cc581f32bf
2 changed files with 18 additions and 6 deletions
|
@ -0,0 +1,2 @@
|
||||||
|
Fix a crash that could occur on Windows when a background thread waits on a
|
||||||
|
:c:type:`PyMutex` while the main thread is shutting down the interpreter.
|
|
@ -112,17 +112,27 @@ _PySemaphore_PlatformWait(_PySemaphore *sema, PyTime_t timeout)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: we wait on the sigint event even in non-main threads to match the
|
HANDLE handles[2] = { sema->platform_sem, NULL };
|
||||||
// behavior of the other platforms. Non-main threads will ignore the
|
HANDLE sigint_event = NULL;
|
||||||
// Py_PARK_INTR result.
|
DWORD count = 1;
|
||||||
HANDLE sigint_event = _PyOS_SigintEvent();
|
if (_Py_IsMainThread()) {
|
||||||
HANDLE handles[2] = { sema->platform_sem, sigint_event };
|
// gh-135099: Wait on the SIGINT event only in the main thread. Other
|
||||||
DWORD count = sigint_event != NULL ? 2 : 1;
|
// threads would ignore the result anyways, and accessing
|
||||||
|
// `_PyOS_SigintEvent()` from non-main threads may race with
|
||||||
|
// interpreter shutdown, which closes the event handle. Note that
|
||||||
|
// non-main interpreters will ignore the result.
|
||||||
|
sigint_event = _PyOS_SigintEvent();
|
||||||
|
if (sigint_event != NULL) {
|
||||||
|
handles[1] = sigint_event;
|
||||||
|
count = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
wait = WaitForMultipleObjects(count, handles, FALSE, millis);
|
wait = WaitForMultipleObjects(count, handles, FALSE, millis);
|
||||||
if (wait == WAIT_OBJECT_0) {
|
if (wait == WAIT_OBJECT_0) {
|
||||||
res = Py_PARK_OK;
|
res = Py_PARK_OK;
|
||||||
}
|
}
|
||||||
else if (wait == WAIT_OBJECT_0 + 1) {
|
else if (wait == WAIT_OBJECT_0 + 1) {
|
||||||
|
assert(sigint_event != NULL);
|
||||||
ResetEvent(sigint_event);
|
ResetEvent(sigint_event);
|
||||||
res = Py_PARK_INTR;
|
res = Py_PARK_INTR;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue