Skip to content

Commit feaf0c3

Browse files
authored
[3.7] bpo-39847: EnterNonRecursiveMutex() uses GetTickCount64() (GH-18780) (GH-18959)
The 32-bit (49-day) TickCount relied on in EnterNonRecursiveMutex can overflow in the gap between the 'target' time and the 'now' time WaitForSingleObjectEx returns, causing the loop to think it needs to wait another 49 days. This is most likely to happen when the machine is hibernated during WaitForSingleObjectEx. This makes acquiring a lock/event/etc from the _thread or threading module appear to never timeout. Replace with GetTickCount64 - this is OK now Python no longer supports XP which lacks it, and is in use for time.monotonic(). Co-authored-by: And Clover <[email protected]> (cherry picked from commit 64838ce) Co-authored-by: bobince <[email protected]>
1 parent 6a12676 commit feaf0c3

File tree

2 files changed

+5
-3
lines changed

2 files changed

+5
-3
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Avoid hang when computer is hibernated whilst waiting for a mutex (for
2+
lock-related objects from :mod:`threading`) around 49-day uptime.

Python/thread_nt.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,16 +75,16 @@ EnterNonRecursiveMutex(PNRMUTEX mutex, DWORD milliseconds)
7575
}
7676
} else if (milliseconds != 0) {
7777
/* wait at least until the target */
78-
DWORD now, target = GetTickCount() + milliseconds;
78+
ULONGLONG now, target = GetTickCount64() + milliseconds;
7979
while (mutex->locked) {
8080
if (PyCOND_TIMEDWAIT(&mutex->cv, &mutex->cs, (long long)milliseconds*1000) < 0) {
8181
result = WAIT_FAILED;
8282
break;
8383
}
84-
now = GetTickCount();
84+
now = GetTickCount64();
8585
if (target <= now)
8686
break;
87-
milliseconds = target-now;
87+
milliseconds = (DWORD)(target-now);
8888
}
8989
}
9090
if (!mutex->locked) {

0 commit comments

Comments
 (0)