Skip to content

Commit d854562

Browse files
committed
Issue #11618: Fix the timeout logic in threading.Lock.acquire() under
Windows.
2 parents 3c136e1 + 7899acf commit d854562

File tree

3 files changed

+20
-59
lines changed

3 files changed

+20
-59
lines changed

Lib/test/lock_tests.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,16 @@ def f():
213213
lock.acquire()
214214
lock.release()
215215

216+
def test_state_after_timeout(self):
217+
# Issue #11618: check that lock is in a proper state after a
218+
# (non-zero) timeout.
219+
lock = self.locktype()
220+
lock.acquire()
221+
self.assertFalse(lock.acquire(timeout=0.01))
222+
lock.release()
223+
self.assertFalse(lock.locked())
224+
self.assertTrue(lock.acquire(blocking=False))
225+
216226

217227
class RLockTests(BaseLockTests):
218228
"""

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ Core and Builtins
8787
Library
8888
-------
8989

90+
- Issue #11618: Fix the timeout logic in threading.Lock.acquire() under Windows.
91+
9092
- Removed the 'strict' argument to email.parser.Parser, which has been
9193
deprecated since Python 2.4.
9294

Python/thread_nt.h

Lines changed: 8 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -9,82 +9,31 @@
99
#include <process.h>
1010
#endif
1111

12-
typedef struct NRMUTEX {
13-
LONG owned ;
14-
DWORD thread_id ;
15-
HANDLE hevent ;
16-
} NRMUTEX, *PNRMUTEX ;
12+
#define PNRMUTEX HANDLE
1713

18-
19-
BOOL
20-
InitializeNonRecursiveMutex(PNRMUTEX mutex)
14+
PNRMUTEX
15+
AllocNonRecursiveMutex()
2116
{
22-
mutex->owned = -1 ; /* No threads have entered NonRecursiveMutex */
23-
mutex->thread_id = 0 ;
24-
mutex->hevent = CreateEvent(NULL, FALSE, FALSE, NULL) ;
25-
return mutex->hevent != NULL ; /* TRUE if the mutex is created */
17+
return CreateSemaphore(NULL, 1, 1, NULL);
2618
}
2719

2820
VOID
29-
DeleteNonRecursiveMutex(PNRMUTEX mutex)
21+
FreeNonRecursiveMutex(PNRMUTEX mutex)
3022
{
3123
/* No in-use check */
32-
CloseHandle(mutex->hevent) ;
33-
mutex->hevent = NULL ; /* Just in case */
24+
CloseHandle(mutex);
3425
}
3526

3627
DWORD
3728
EnterNonRecursiveMutex(PNRMUTEX mutex, DWORD milliseconds)
3829
{
39-
/* Assume that the thread waits successfully */
40-
DWORD ret ;
41-
42-
/* InterlockedIncrement(&mutex->owned) == 0 means that no thread currently owns the mutex */
43-
if (milliseconds == 0)
44-
{
45-
if (InterlockedCompareExchange(&mutex->owned, 0, -1) != -1)
46-
return WAIT_TIMEOUT ;
47-
ret = WAIT_OBJECT_0 ;
48-
}
49-
else
50-
ret = InterlockedIncrement(&mutex->owned) ?
51-
/* Some thread owns the mutex, let's wait... */
52-
WaitForSingleObject(mutex->hevent, milliseconds) : WAIT_OBJECT_0 ;
53-
54-
mutex->thread_id = GetCurrentThreadId() ; /* We own it */
55-
return ret ;
30+
return WaitForSingleObject(mutex, milliseconds);
5631
}
5732

5833
BOOL
5934
LeaveNonRecursiveMutex(PNRMUTEX mutex)
6035
{
61-
/* We don't own the mutex */
62-
mutex->thread_id = 0 ;
63-
return
64-
InterlockedDecrement(&mutex->owned) < 0 ||
65-
SetEvent(mutex->hevent) ; /* Other threads are waiting, wake one on them up */
66-
}
67-
68-
PNRMUTEX
69-
AllocNonRecursiveMutex(void)
70-
{
71-
PNRMUTEX mutex = (PNRMUTEX)malloc(sizeof(NRMUTEX)) ;
72-
if (mutex && !InitializeNonRecursiveMutex(mutex))
73-
{
74-
free(mutex) ;
75-
mutex = NULL ;
76-
}
77-
return mutex ;
78-
}
79-
80-
void
81-
FreeNonRecursiveMutex(PNRMUTEX mutex)
82-
{
83-
if (mutex)
84-
{
85-
DeleteNonRecursiveMutex(mutex) ;
86-
free(mutex) ;
87-
}
36+
return ReleaseSemaphore(mutex, 1, NULL);
8837
}
8938

9039
long PyThread_get_thread_ident(void);

0 commit comments

Comments
 (0)