Commit 7899acfc authored by Antoine Pitrou's avatar Antoine Pitrou

Issue #11618: Fix the timeout logic in threading.Lock.acquire() under

Windows.
parent 8c5b7480
...@@ -213,6 +213,16 @@ class LockTests(BaseLockTests): ...@@ -213,6 +213,16 @@ class LockTests(BaseLockTests):
lock.acquire() lock.acquire()
lock.release() 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): class RLockTests(BaseLockTests):
""" """
......
...@@ -49,6 +49,8 @@ Core and Builtins ...@@ -49,6 +49,8 @@ Core and Builtins
Library Library
------- -------
- Issue #11618: Fix the timeout logic in threading.Lock.acquire() under Windows.
- Issue #11256: Fix inspect.getcallargs on functions that take only keyword - Issue #11256: Fix inspect.getcallargs on functions that take only keyword
arguments. arguments.
......
...@@ -9,82 +9,31 @@ ...@@ -9,82 +9,31 @@
#include <process.h> #include <process.h>
#endif #endif
typedef struct NRMUTEX { #define PNRMUTEX HANDLE
LONG owned ;
DWORD thread_id ;
HANDLE hevent ;
} NRMUTEX, *PNRMUTEX ;
PNRMUTEX
BOOL AllocNonRecursiveMutex()
InitializeNonRecursiveMutex(PNRMUTEX mutex)
{ {
mutex->owned = -1 ; /* No threads have entered NonRecursiveMutex */ return CreateSemaphore(NULL, 1, 1, NULL);
mutex->thread_id = 0 ;
mutex->hevent = CreateEvent(NULL, FALSE, FALSE, NULL) ;
return mutex->hevent != NULL ; /* TRUE if the mutex is created */
} }
VOID VOID
DeleteNonRecursiveMutex(PNRMUTEX mutex) FreeNonRecursiveMutex(PNRMUTEX mutex)
{ {
/* No in-use check */ /* No in-use check */
CloseHandle(mutex->hevent) ; CloseHandle(mutex);
mutex->hevent = NULL ; /* Just in case */
} }
DWORD DWORD
EnterNonRecursiveMutex(PNRMUTEX mutex, DWORD milliseconds) EnterNonRecursiveMutex(PNRMUTEX mutex, DWORD milliseconds)
{ {
/* Assume that the thread waits successfully */ return WaitForSingleObject(mutex, milliseconds);
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 ;
} }
BOOL BOOL
LeaveNonRecursiveMutex(PNRMUTEX mutex) LeaveNonRecursiveMutex(PNRMUTEX mutex)
{ {
/* We don't own the mutex */ return ReleaseSemaphore(mutex, 1, NULL);
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) ;
}
} }
long PyThread_get_thread_ident(void); long PyThread_get_thread_ident(void);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment