diff options
author | Antoine Pitrou <solipsis@pitrou.net> | 2011-11-21 20:26:56 (GMT) |
---|---|---|
committer | Antoine Pitrou <solipsis@pitrou.net> | 2011-11-21 20:26:56 (GMT) |
commit | 6dd381eb62278f75de7ba01626813de84cd248e7 (patch) | |
tree | 4b843b5767b3296212c5dbe8c696c1081b2fbfe0 /Modules/_multiprocessing/semaphore.c | |
parent | ce4a9da70535b4bb9048147b141f01004af2133d (diff) | |
download | cpython-6dd381eb62278f75de7ba01626813de84cd248e7.zip cpython-6dd381eb62278f75de7ba01626813de84cd248e7.tar.gz cpython-6dd381eb62278f75de7ba01626813de84cd248e7.tar.bz2 |
Issue #12328: Under Windows, refactor handling of Ctrl-C events and
make _multiprocessing.win32.WaitForMultipleObjects interruptible when
the wait_flag parameter is false. Patch by sbt.
Diffstat (limited to 'Modules/_multiprocessing/semaphore.c')
-rw-r--r-- | Modules/_multiprocessing/semaphore.c | 52 |
1 files changed, 20 insertions, 32 deletions
diff --git a/Modules/_multiprocessing/semaphore.c b/Modules/_multiprocessing/semaphore.c index 6749f23..e48936e 100644 --- a/Modules/_multiprocessing/semaphore.c +++ b/Modules/_multiprocessing/semaphore.c @@ -62,7 +62,8 @@ semlock_acquire(SemLockObject *self, PyObject *args, PyObject *kwds) int blocking = 1; double timeout; PyObject *timeout_obj = Py_None; - DWORD res, full_msecs, msecs, start, ticks; + DWORD res, full_msecs, nhandles; + HANDLE handles[2], sigint_event; static char *kwlist[] = {"block", "timeout", NULL}; @@ -96,53 +97,40 @@ semlock_acquire(SemLockObject *self, PyObject *args, PyObject *kwds) Py_RETURN_TRUE; } - /* check whether we can acquire without blocking */ + /* check whether we can acquire without releasing the GIL and blocking */ if (WaitForSingleObject(self->handle, 0) == WAIT_OBJECT_0) { self->last_tid = GetCurrentThreadId(); ++self->count; Py_RETURN_TRUE; } - msecs = full_msecs; - start = GetTickCount(); - - for ( ; ; ) { - HANDLE handles[2] = {self->handle, sigint_event}; + /* prepare list of handles */ + nhandles = 0; + handles[nhandles++] = self->handle; + if (_PyOS_IsMainThread()) { + sigint_event = _PyOS_SigintEvent(); + assert(sigint_event != NULL); + handles[nhandles++] = sigint_event; + } - /* do the wait */ - Py_BEGIN_ALLOW_THREADS + /* do the wait */ + Py_BEGIN_ALLOW_THREADS + if (sigint_event != NULL) ResetEvent(sigint_event); - res = WaitForMultipleObjects(2, handles, FALSE, msecs); - Py_END_ALLOW_THREADS - - /* handle result */ - if (res != WAIT_OBJECT_0 + 1) - break; - - /* got SIGINT so give signal handler a chance to run */ - Sleep(1); - - /* if this is main thread let KeyboardInterrupt be raised */ - if (PyErr_CheckSignals()) - return NULL; - - /* recalculate timeout */ - if (msecs != INFINITE) { - ticks = GetTickCount(); - if ((DWORD)(ticks - start) >= full_msecs) - Py_RETURN_FALSE; - msecs = full_msecs - (ticks - start); - } - } + res = WaitForMultipleObjects(nhandles, handles, FALSE, full_msecs); + Py_END_ALLOW_THREADS /* handle result */ switch (res) { case WAIT_TIMEOUT: Py_RETURN_FALSE; - case WAIT_OBJECT_0: + case WAIT_OBJECT_0 + 0: self->last_tid = GetCurrentThreadId(); ++self->count; Py_RETURN_TRUE; + case WAIT_OBJECT_0 + 1: + errno = EINTR; + return PyErr_SetFromErrno(PyExc_IOError); case WAIT_FAILED: return PyErr_SetFromWindowsErr(0); default: |