X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Frts%2Fwin32%2FIOManager.c;h=96e5794031b94a9d3bc09fd168f1adeff4a2283a;hb=900ca61d2d1c61cb5a100dbcd67c265c89bbc8b5;hp=b8b79426522220bd20876965c2fffdad1e01c2d2;hpb=ce42f19f8c840fbe89844471a0d850d310a94556;p=ghc-hetmet.git diff --git a/ghc/rts/win32/IOManager.c b/ghc/rts/win32/IOManager.c index b8b7942..96e5794 100644 --- a/ghc/rts/win32/IOManager.c +++ b/ghc/rts/win32/IOManager.c @@ -42,7 +42,7 @@ IOWorkerProc(PVOID param) WorkQueue* pq = iom->workQueue; WorkItem* work; int len = 0, fd = 0; - DWORD errCode; + DWORD errCode = 0; void* complData; hWaits[0] = (HANDLE)iom->hExitEvent; @@ -70,6 +70,11 @@ IOWorkerProc(PVOID param) */ rc = WaitForMultipleObjects( 2, hWaits, FALSE, INFINITE ); + if (rc == WAIT_OBJECT_0) { + // we received the exit event + return 0; + } + EnterCriticalSection(&iom->manLock); /* Signal that the thread is 'non-idle' and about to consume * a work item. @@ -78,10 +83,7 @@ IOWorkerProc(PVOID param) iom->queueSize--; LeaveCriticalSection(&iom->manLock); - if ( WAIT_OBJECT_0 == rc ) { - /* shutdown */ - return 0; - } else if ( (WAIT_OBJECT_0 + 1) == rc ) { + if ( rc == (WAIT_OBJECT_0 + 1) ) { /* work item available, fetch it. */ if (FetchWork(pq,(void**)&work)) { if ( work->workKind & WORKER_READ ) { @@ -94,9 +96,40 @@ IOWorkerProc(PVOID param) errCode = WSAGetLastError(); } } else { + DWORD dw; + + /* Do the read(), with extra-special handling for Ctrl+C */ len = read(work->workData.ioData.fd, work->workData.ioData.buf, work->workData.ioData.len); + if ( len == 0 && work->workData.ioData.len != 0 ) { + /* Given the following scenario: + * - a console handler has been registered that handles Ctrl+C + * events. + * - we've not tweaked the 'console mode' settings to turn on + * ENABLE_PROCESSED_INPUT. + * - we're blocked waiting on input from standard input. + * - the user hits Ctrl+C. + * + * The OS will invoke the console handler (in a separate OS thread), + * and the above read() (i.e., under the hood, a ReadFile() op) returns + * 0, with the error set to ERROR_OPERATION_ABORTED. We don't + * want to percolate this non-EOF condition too far back up, but ignore + * it. However, we do want to give the RTS an opportunity to deliver the + * console event. + * + * Hence, we set 'errorCode' to (-2), which we then look out for in + * GHC.Conc.asyncRead. + */ + dw = GetLastError(); + if ( dw == ERROR_OPERATION_ABORTED ) { + /* Only do the retry when dealing with the standard input handle. */ + HANDLE h = (HANDLE)GetStdHandle(STD_INPUT_HANDLE); + if ( _get_osfhandle(work->workData.ioData.fd) == (long)h ) { + errCode = (DWORD)-2; + } + } + } if (len == -1) { errCode = errno; } } complData = work->workData.ioData.buf; @@ -363,9 +396,12 @@ AddProcRequest ( void* proc, return depositWorkItem(reqID, wItem); } -void ShutdownIOManager() +void ShutdownIOManager ( void ) { SetEvent(ioMan->hExitEvent); - free(ioMan); - ioMan = NULL; + // ToDo: we can't free this now, because the worker thread(s) + // haven't necessarily finished with it yet. Perhaps it should + // have a reference count or something. + // free(ioMan); + // ioMan = NULL; }