summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2011-03-30 23:03:10 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2011-03-30 23:03:10 (GMT)
commitd85456279f129e19a3f4c8ba0b3d05f5bdbfca1d (patch)
treeb6dba00c7a9e08d4dcb12a96106186df8debd48c
parent3c136e19b9de13f8d4163a0feb3af54ab8b8c765 (diff)
parent7899acfc23c6262cea8f69bda36cf256cdfc3501 (diff)
downloadcpython-d85456279f129e19a3f4c8ba0b3d05f5bdbfca1d.zip
cpython-d85456279f129e19a3f4c8ba0b3d05f5bdbfca1d.tar.gz
cpython-d85456279f129e19a3f4c8ba0b3d05f5bdbfca1d.tar.bz2
Issue #11618: Fix the timeout logic in threading.Lock.acquire() under
Windows.
-rw-r--r--Lib/test/lock_tests.py10
-rw-r--r--Misc/NEWS2
-rw-r--r--Python/thread_nt.h67
3 files changed, 20 insertions, 59 deletions
diff --git a/Lib/test/lock_tests.py b/Lib/test/lock_tests.py
index b6d818e..005c912 100644
--- a/Lib/test/lock_tests.py
+++ b/Lib/test/lock_tests.py
@@ -213,6 +213,16 @@ class LockTests(BaseLockTests):
lock.acquire()
lock.release()
+ def test_state_after_timeout(self):
+ # Issue #11618: check that lock is in a proper state after a
+ # (non-zero) timeout.
+ lock = self.locktype()
+ lock.acquire()
+ self.assertFalse(lock.acquire(timeout=0.01))
+ lock.release()
+ self.assertFalse(lock.locked())
+ self.assertTrue(lock.acquire(blocking=False))
+
class RLockTests(BaseLockTests):
"""
diff --git a/Misc/NEWS b/Misc/NEWS
index f276cb3..33d9997 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -87,6 +87,8 @@ Core and Builtins
Library
-------
+- Issue #11618: Fix the timeout logic in threading.Lock.acquire() under Windows.
+
- Removed the 'strict' argument to email.parser.Parser, which has been
deprecated since Python 2.4.
diff --git a/Python/thread_nt.h b/Python/thread_nt.h
index 684b545..d1bb0e5 100644
--- a/Python/thread_nt.h
+++ b/Python/thread_nt.h
@@ -9,82 +9,31 @@
#include <process.h>
#endif
-typedef struct NRMUTEX {
- LONG owned ;
- DWORD thread_id ;
- HANDLE hevent ;
-} NRMUTEX, *PNRMUTEX ;
+#define PNRMUTEX HANDLE
-
-BOOL
-InitializeNonRecursiveMutex(PNRMUTEX mutex)
+PNRMUTEX
+AllocNonRecursiveMutex()
{
- mutex->owned = -1 ; /* No threads have entered NonRecursiveMutex */
- mutex->thread_id = 0 ;
- mutex->hevent = CreateEvent(NULL, FALSE, FALSE, NULL) ;
- return mutex->hevent != NULL ; /* TRUE if the mutex is created */
+ return CreateSemaphore(NULL, 1, 1, NULL);
}
VOID
-DeleteNonRecursiveMutex(PNRMUTEX mutex)
+FreeNonRecursiveMutex(PNRMUTEX mutex)
{
/* No in-use check */
- CloseHandle(mutex->hevent) ;
- mutex->hevent = NULL ; /* Just in case */
+ CloseHandle(mutex);
}
DWORD
EnterNonRecursiveMutex(PNRMUTEX mutex, DWORD milliseconds)
{
- /* Assume that the thread waits successfully */
- DWORD ret ;
-
- /* InterlockedIncrement(&mutex->owned) == 0 means that no thread currently owns the mutex */
- if (milliseconds == 0)
- {
- if (InterlockedCompareExchange(&mutex->owned, 0, -1) != -1)
- return WAIT_TIMEOUT ;
- ret = WAIT_OBJECT_0 ;
- }
- else
- ret = InterlockedIncrement(&mutex->owned) ?
- /* Some thread owns the mutex, let's wait... */
- WaitForSingleObject(mutex->hevent, milliseconds) : WAIT_OBJECT_0 ;
-
- mutex->thread_id = GetCurrentThreadId() ; /* We own it */
- return ret ;
+ return WaitForSingleObject(mutex, milliseconds);
}
BOOL
LeaveNonRecursiveMutex(PNRMUTEX mutex)
{
- /* We don't own the mutex */
- mutex->thread_id = 0 ;
- return
- InterlockedDecrement(&mutex->owned) < 0 ||
- SetEvent(mutex->hevent) ; /* Other threads are waiting, wake one on them up */
-}
-
-PNRMUTEX
-AllocNonRecursiveMutex(void)
-{
- PNRMUTEX mutex = (PNRMUTEX)malloc(sizeof(NRMUTEX)) ;
- if (mutex && !InitializeNonRecursiveMutex(mutex))
- {
- free(mutex) ;
- mutex = NULL ;
- }
- return mutex ;
-}
-
-void
-FreeNonRecursiveMutex(PNRMUTEX mutex)
-{
- if (mutex)
- {
- DeleteNonRecursiveMutex(mutex) ;
- free(mutex) ;
- }
+ return ReleaseSemaphore(mutex, 1, NULL);
}
long PyThread_get_thread_ident(void);