Skip to content

Commit

Permalink
pythongh-125541: Make Ctrl-C interrupt threading.Lock.acquire() on …
Browse files Browse the repository at this point in the history
…Windows (python#125546)
  • Loading branch information
colesbury authored Oct 17, 2024
1 parent b454662 commit d8c8648
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 8 deletions.
9 changes: 3 additions & 6 deletions Doc/library/_thread.rst
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,9 @@ Lock objects have the following methods:
.. versionchanged:: 3.2
Lock acquires can now be interrupted by signals on POSIX.

.. versionchanged:: 3.14
Lock acquires can now be interrupted by signals on Windows.


.. method:: lock.release()

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

* It is platform-dependent whether the :meth:`~threading.Lock.acquire` method
on a lock can be interrupted (so that the :exc:`KeyboardInterrupt` exception
will happen immediately, rather than only after the lock has been acquired or
the operation has timed out). It can be interrupted on POSIX, but not on
Windows.

* When the main thread exits, it is system defined whether the other threads
survive. On most systems, they are killed without executing
:keyword:`try` ... :keyword:`finally` clauses or executing object
Expand Down
3 changes: 3 additions & 0 deletions Doc/library/threading.rst
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,9 @@ All methods are executed atomically.
Lock acquisition can now be interrupted by signals on POSIX if the
underlying threading implementation supports it.

.. versionchanged:: 3.14
Lock acquisition can now be interrupted by signals on Windows.


.. method:: release()

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Pressing :kbd:`Ctrl-C` while blocked in :meth:`threading.Lock.acquire`,
:meth:`threading.RLock.acquire`, and :meth:`threading.Thread.join` now
interrupts the function call and raises a :exc:`KeyboardInterrupt` exception
on Windows, similar to how those functions behave on macOS and Linux.
17 changes: 15 additions & 2 deletions Python/parking_lot.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,15 +111,28 @@ _PySemaphore_PlatformWait(_PySemaphore *sema, PyTime_t timeout)
millis = (DWORD) div;
}
}
wait = WaitForSingleObjectEx(sema->platform_sem, millis, FALSE);

// NOTE: we wait on the sigint event even in non-main threads to match the
// behavior of the other platforms. Non-main threads will ignore the
// Py_PARK_INTR result.
HANDLE sigint_event = _PyOS_SigintEvent();
HANDLE handles[2] = { sema->platform_sem, sigint_event };
DWORD count = sigint_event != NULL ? 2 : 1;
wait = WaitForMultipleObjects(count, handles, FALSE, millis);
if (wait == WAIT_OBJECT_0) {
res = Py_PARK_OK;
}
else if (wait == WAIT_OBJECT_0 + 1) {
ResetEvent(sigint_event);
res = Py_PARK_INTR;
}
else if (wait == WAIT_TIMEOUT) {
res = Py_PARK_TIMEOUT;
}
else {
res = Py_PARK_INTR;
_Py_FatalErrorFormat(__func__,
"unexpected error from semaphore: %u (error: %u)",
wait, GetLastError());
}
#elif defined(_Py_USE_SEMAPHORES)
int err;
Expand Down

0 comments on commit d8c8648

Please sign in to comment.