@@ -62,7 +62,8 @@ semlock_acquire(SemLockObject *self, PyObject *args, PyObject *kwds)
6262 int blocking = 1 ;
6363 double timeout ;
6464 PyObject * timeout_obj = Py_None ;
65- DWORD res , full_msecs , msecs , start , ticks ;
65+ DWORD res , full_msecs , nhandles ;
66+ HANDLE handles [2 ], sigint_event ;
6667
6768 static char * kwlist [] = {"block" , "timeout" , NULL };
6869
@@ -96,53 +97,40 @@ semlock_acquire(SemLockObject *self, PyObject *args, PyObject *kwds)
9697 Py_RETURN_TRUE ;
9798 }
9899
99- /* check whether we can acquire without blocking */
100+ /* check whether we can acquire without releasing the GIL and blocking */
100101 if (WaitForSingleObject (self -> handle , 0 ) == WAIT_OBJECT_0 ) {
101102 self -> last_tid = GetCurrentThreadId ();
102103 ++ self -> count ;
103104 Py_RETURN_TRUE ;
104105 }
105106
106- msecs = full_msecs ;
107- start = GetTickCount ();
108-
109- for ( ; ; ) {
110- HANDLE handles [2 ] = {self -> handle , sigint_event };
107+ /* prepare list of handles */
108+ nhandles = 0 ;
109+ handles [nhandles ++ ] = self -> handle ;
110+ if (_PyOS_IsMainThread ()) {
111+ sigint_event = _PyOS_SigintEvent ();
112+ assert (sigint_event != NULL );
113+ handles [nhandles ++ ] = sigint_event ;
114+ }
111115
112- /* do the wait */
113- Py_BEGIN_ALLOW_THREADS
116+ /* do the wait */
117+ Py_BEGIN_ALLOW_THREADS
118+ if (sigint_event != NULL)
114119 ResetEvent (sigint_event );
115- res = WaitForMultipleObjects (2 , handles , FALSE, msecs );
116- Py_END_ALLOW_THREADS
117-
118- /* handle result */
119- if (res != WAIT_OBJECT_0 + 1 )
120- break ;
121-
122- /* got SIGINT so give signal handler a chance to run */
123- Sleep (1 );
124-
125- /* if this is main thread let KeyboardInterrupt be raised */
126- if (PyErr_CheckSignals ())
127- return NULL ;
128-
129- /* recalculate timeout */
130- if (msecs != INFINITE ) {
131- ticks = GetTickCount ();
132- if ((DWORD )(ticks - start ) >= full_msecs )
133- Py_RETURN_FALSE ;
134- msecs = full_msecs - (ticks - start );
135- }
136- }
120+ res = WaitForMultipleObjects (nhandles , handles , FALSE , full_msecs );
121+ Py_END_ALLOW_THREADS
137122
138123 /* handle result */
139124 switch (res ) {
140125 case WAIT_TIMEOUT :
141126 Py_RETURN_FALSE ;
142- case WAIT_OBJECT_0 :
127+ case WAIT_OBJECT_0 + 0 :
143128 self -> last_tid = GetCurrentThreadId ();
144129 ++ self -> count ;
145130 Py_RETURN_TRUE ;
131+ case WAIT_OBJECT_0 + 1 :
132+ errno = EINTR ;
133+ return PyErr_SetFromErrno (PyExc_IOError );
146134 case WAIT_FAILED :
147135 return PyErr_SetFromWindowsErr (0 );
148136 default :
0 commit comments