10000 gh-125541: Make Ctrl-C interrupt `threading.Lock.acquire()` on Windows · colesbury/cpython@8b3e7ae · GitHub
[go: up one dir, main page]

Skip to content

Commit 8b3e7ae

Browse files
committed
pythongh-125541: Make Ctrl-C interrupt threading.Lock.acquire() on Windows
1 parent aac89b5 commit 8b3e7ae

File tree

3 files changed

+19
-2
lines changed

3 files changed

+19
-2
lines changed

Doc/library/_thread.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,9 @@ Lock objects have the following methods:
187187
.. versionchanged:: 3.2
188188
Lock acquires can now be interrupted by signals on POSIX.
189189

190+
.. versionchanged:: 3.14
191+
Lock acquires can now be interrupted by signals on Windows.
192+
190193

191194
.. method:: lock.release()
192195

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Pressing :kbd:`Ctrl-C` while blocked in :meth:`threading.Lock.acquire` now
2+
interrupts the function and raises a :exc:`KeyboardInterrupt` exception on
3+
Windows, similar to how it behaves on macOS and Linux.

Python/parking_lot.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,15 +111,26 @@ _PySemaphore_PlatformWait(_PySemaphore *sema, PyTime_t timeout)
111111
millis = (DWORD) div;
112112
}
113113
}
114-
wait = WaitForSingleObjectEx(sema->platform_sem, millis, FALSE);
114+
115+
HANDLE sigint_event = _PyOS_SigintEvent();
116+
HANDLE handles[2] = {sema->platform_sem, sigint_event};
117+
// Only wait for the sigint_event if we are in the main thread
118+
DWORD num_handles = _PyOS_IsMainThread() ? 2 : 1;
119+
wait = WaitForMultipleObjectsEx(num_handles, handles, FALSE, millis, FALSE);
115120
if (wait == WAIT_OBJECT_0) {
116121
res = Py_PARK_OK;
117122
}
123+
else if (wait == WAIT_OBJECT_0 + 1) {
124+
ResetEvent(sigint_event);
125+
res = Py_PARK_INTR;
126+
}
118127
else if (wait == WAIT_TIMEOUT) {
119128
res = Py_PARK_TIMEOUT;
120129
}
121130
else {
122-
res = Py_PARK_INTR;
131+
_Py_FatalErrorFormat(__func__,
132+
"unexpected error from semaphore: %u (error: %u)",
133+
wait, GetLastError());
123134
}
124135
#elif defined(_Py_USE_SEMAPHORES)
125136
int err;

0 commit comments

Comments
 (0)
0