8000 gh-125541: Make Ctrl-C interrupt `threading.Lock.acquire()` on Window… · python/cpython@d8c8648 · GitHub
[go: up one dir, main page]

Skip to content

Commit d8c8648

Browse files
authored
gh-125541: Make Ctrl-C interrupt threading.Lock.acquire() on Windows (#125546)
1 parent b454662 commit d8c8648

File tree

4 files changed

+25
-8
lines changed

4 files changed

+25
-8
lines changed

Doc/library/_thread.rst

Lines changed: 3 additions & 6 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

@@ -219,12 +222,6 @@ In addition to these methods, lock objects can also be used via the
219222
* Calling :func:`sys.exit` or raising the :exc:`SystemExit` exception is
220223
equivalent to calling :func:`_thread.exit`.
221224

222-
* It is platform-dependent whether the :meth:`~threading.Lock.acquire` method
223-
on a lock can be interrupted (so that the :exc:`KeyboardInterrupt` exception
224-
will happen immediately, rather than only after the lock has been acquired or
225-
the operation has timed out). It can be interrupted on POSIX, but not on
226-
Windows.
227-
228225
* When the main thread exits, it is system defined whether the other threads
229226
survive. On most systems, they are killed without executing
230227
:keyword:`try` ... :keyword:`finally` clauses or executing object

Doc/library/threading.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,9 @@ All methods are executed atomically.
567567
Lock acquisition can now be interrupted by signals on POSIX if the
568568
underlying threading implementation supports it.
569569

570+
.. versionchanged:: 3.14
571+
Lock acquisition can now be interrupted by signals on Windows.
572+
570573

571574
.. method:: release()
572575

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

Python/parking_lot.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,15 +111,28 @@ _PySemaphore_PlatformWait(_PySemaphore *sema, PyTime_t timeout)
111111
millis = (DWORD) div;
112112
}
113113
}
114-
wait = WaitForSingleObjectEx(sema->platform_sem, millis, FALSE);
114+
115+
// NOTE: we wait on the sigint event even in non-main threads to match the
116+
// behavior of the other platforms. Non-main threads will ignore the
117+
// Py_PARK_INTR result.
118+
HANDLE sigint_event = _PyOS_SigintEvent();
119+
HANDLE handles[2] = { sema->platform_sem, sigint_event };
120+
DWORD count = sigint_event != NULL ? 2 : 1;
121+
wait = WaitForMultipleObjects(count, handles, FALSE, millis);
115122
if (wait == WAIT_OBJECT_0) {
116123
res = Py_PARK_OK;
117124
}
125+
else if (wait == WAIT_OBJECT_0 + 1) {
126+
ResetEvent(sigint_event);
127+
res = Py_PARK_INTR;
128+
}
118129
else if (wait == WAIT_TIMEOUT) {
119130
res = Py_PARK_TIMEOUT;
120131
}
121132
else {
122-
res = Py_PARK_INTR;
133+
_Py_FatalErrorFormat(__func__,
134+
"unexpected error from semaphore: %u (error: %u)",
135+
wait, GetLastError());
123136
}
124137
#elif defined(_Py_USE_SEMAPHORES)
125138
int err;

0 commit comments

Comments
 (0)
0