[Python-checkins] bpo-41710: Fix PY_TIMEOUT_MAX on Windows (GH-28673)

vstinner webhook-mailer at python.org
Fri Oct 1 07:03:07 EDT 2021


https://github.com/python/cpython/commit/98d282700221234157159df4af76423d89490ad9
commit: 98d282700221234157159df4af76423d89490ad9
branch: main
author: Victor Stinner <vstinner at python.org>
committer: vstinner <vstinner at python.org>
date: 2021-10-01T13:03:03+02:00
summary:

bpo-41710: Fix PY_TIMEOUT_MAX on Windows (GH-28673)

WaitForSingleObject() accepts timeout in milliseconds in the range
[0; 0xFFFFFFFE] (DWORD type). INFINITE value (0xFFFFFFFF) means no
timeout. 0xFFFFFFFE milliseconds is around 49.7 days.

PY_TIMEOUT_MAX is (0xFFFFFFFE * 1000) milliseconds on Windows, around
49.7 days.

Partially revert commit 37b8294d6295ca12553fd7c98778be71d24f4b24.

files:
D Misc/NEWS.d/next/Library/2021-09-30-08-57-50.bpo-41710.JMsPAW.rst
M Include/pythread.h
M Python/thread_nt.h

diff --git a/Include/pythread.h b/Include/pythread.h
index cf4cc9a7473f1..1a6092c4ad0be 100644
--- a/Include/pythread.h
+++ b/Include/pythread.h
@@ -61,11 +61,11 @@ PyAPI_FUNC(int) _PyThread_at_fork_reinit(PyThread_type_lock *lock);
       convert microseconds to nanoseconds. */
 #  define PY_TIMEOUT_MAX (LLONG_MAX / 1000)
 #elif defined (NT_THREADS)
-   /* In the NT API, the timeout is a DWORD and is expressed in milliseconds,
-    * a positive number between 0 and 0x7FFFFFFF (see WaitForSingleObject()
-    * documentation). */
-#  if 0x7FFFFFFFLL * 1000 < LLONG_MAX
-#    define PY_TIMEOUT_MAX (0x7FFFFFFFLL * 1000)
+   // WaitForSingleObject() accepts timeout in milliseconds in the range
+   // [0; 0xFFFFFFFE] (DWORD type). INFINITE value (0xFFFFFFFF) means no
+   // timeout. 0xFFFFFFFE milliseconds is around 49.7 days.
+#  if 0xFFFFFFFELL * 1000 < LLONG_MAX
+#    define PY_TIMEOUT_MAX (0xFFFFFFFELL * 1000)
 #  else
 #    define PY_TIMEOUT_MAX LLONG_MAX
 #  endif
diff --git a/Misc/NEWS.d/next/Library/2021-09-30-08-57-50.bpo-41710.JMsPAW.rst b/Misc/NEWS.d/next/Library/2021-09-30-08-57-50.bpo-41710.JMsPAW.rst
deleted file mode 100644
index 516214a619e8e..0000000000000
--- a/Misc/NEWS.d/next/Library/2021-09-30-08-57-50.bpo-41710.JMsPAW.rst
+++ /dev/null
@@ -1,3 +0,0 @@
-Fix :data:`_thread.TIMEOUT_MAX` value on Windows: the maximum timeout is
-0x7FFFFFFF milliseconds (around 24.9 days), not 0xFFFFFFFF milliseconds (around
-49.7 days).
diff --git a/Python/thread_nt.h b/Python/thread_nt.h
index 0beb3d3af2fd3..26f054ff0ce49 100644
--- a/Python/thread_nt.h
+++ b/Python/thread_nt.h
@@ -292,9 +292,10 @@ PyThread_free_lock(PyThread_type_lock aLock)
     FreeNonRecursiveMutex(aLock) ;
 }
 
-// WaitForSingleObject() documentation: "The time-out value needs to be a
-// positive number between 0 and 0x7FFFFFFF." INFINITE is equal to 0xFFFFFFFF.
-const DWORD TIMEOUT_MS_MAX = 0x7FFFFFFF;
+// WaitForSingleObject() accepts timeout in milliseconds in the range
+// [0; 0xFFFFFFFE] (DWORD type). INFINITE value (0xFFFFFFFF) means no
+// timeout. 0xFFFFFFFE milliseconds is around 49.7 days.
+const DWORD TIMEOUT_MS_MAX = 0xFFFFFFFE;
 
 /*
  * Return 1 on success if the lock was acquired
@@ -322,12 +323,11 @@ PyThread_acquire_lock_timed(PyThread_type_lock aLock,
             // overflow to the caller, so clamp the timeout to
             // [0, TIMEOUT_MS_MAX] milliseconds.
             //
-            // TIMEOUT_MS_MAX milliseconds is around 24.9 days.
-            //
             // _thread.Lock.acquire() and _thread.RLock.acquire() raise an
             // OverflowError if microseconds is greater than PY_TIMEOUT_MAX.
             milliseconds = TIMEOUT_MS_MAX;
         }
+        assert(milliseconds != INFINITE);
     }
     else {
         milliseconds = INFINITE;



More information about the Python-checkins mailing list