From c7fd6356eb1ccab4b92fa548d52023cc221fa7c0 Mon Sep 17 00:00:00 2001 From: sof Date: Fri, 21 Jan 2005 19:59:01 +0000 Subject: [PATCH] [project @ 2005-01-21 19:58:51 by sof] win32 only: Tidy up delivery and handling of console events by having the low-level console event handler signal the RTS thread blocked waiting for I/O. --- ghc/rts/Schedule.c | 5 ++++- ghc/rts/win32/ConsoleHandler.c | 10 +++++++++- ghc/rts/win32/IOManager.c | 30 +++++++++++++++++++++++------- 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/ghc/rts/Schedule.c b/ghc/rts/Schedule.c index 6aedb8f..76fec45 100644 --- a/ghc/rts/Schedule.c +++ b/ghc/rts/Schedule.c @@ -542,7 +542,10 @@ schedule( StgMainThread *mainThread USED_WHEN_RTS_SUPPORTS_THREADS, // ToDo: add deadlock detection in GUM (similar to SMP) -- HWL #endif -#if defined(RTS_SUPPORTS_THREADS) +#if defined(RTS_SUPPORTS_THREADS) || defined(mingw32_TARGET_OS) + /* win32: might be back here due to awaitEvent() being abandoned + * as a result of a console event having been delivered. + */ if ( EMPTY_RUN_QUEUE() ) { continue; // nothing to do } diff --git a/ghc/rts/win32/ConsoleHandler.c b/ghc/rts/win32/ConsoleHandler.c index a1d3bd9..a6a53a0 100644 --- a/ghc/rts/win32/ConsoleHandler.c +++ b/ghc/rts/win32/ConsoleHandler.c @@ -9,6 +9,7 @@ #include "Schedule.h" #include "RtsUtils.h" #include "RtsFlags.h" +#include "AsyncIO.h" extern int stg_InstallConsoleEvent(int action, StgStablePtr *handler); @@ -63,6 +64,9 @@ static BOOL WINAPI shutdown_handler(DWORD dwCtrlType) stg_exit(EXIT_INTERRUPTED); } else { interruptStgRts(); + /* Cheesy pulsing of an event to wake up a waiting RTS thread, if any */ + abandonRequestWait(); + resetAbandonRequestWait(); } return TRUE; @@ -197,11 +201,15 @@ static BOOL WINAPI generic_handler(DWORD dwCtrlType) */ return FALSE; default: + if (!deliver_event) return TRUE; + if ( stg_pending_events < N_PENDING_EVENTS ) { stg_pending_buf[stg_pending_events] = dwCtrlType; stg_pending_events++; } - context_switch = 1; + /* Cheesy pulsing of an event to wake up a waiting RTS thread, if any */ + abandonRequestWait(); + resetAbandonRequestWait(); return TRUE; } } diff --git a/ghc/rts/win32/IOManager.c b/ghc/rts/win32/IOManager.c index 96e5794..60f6aa8 100644 --- a/ghc/rts/win32/IOManager.c +++ b/ghc/rts/win32/IOManager.c @@ -98,10 +98,12 @@ IOWorkerProc(PVOID param) } else { DWORD dw; + while (1) { /* Do the read(), with extra-special handling for Ctrl+C */ len = read(work->workData.ioData.fd, work->workData.ioData.buf, work->workData.ioData.len); + dw = GetLastError(); if ( len == 0 && work->workData.ioData.len != 0 ) { /* Given the following scenario: * - a console handler has been registered that handles Ctrl+C @@ -115,20 +117,34 @@ IOWorkerProc(PVOID param) * 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. + * it. + * + * However, we do want to give the RTS an opportunity to deliver the + * console event. Take care of this in the low-level console handler + * in ConsoleHandler.c which wakes up the RTS thread that's blocked + * waiting for I/O results from this worker (and possibly others). + * It won't see any I/O, but notices and dispatches the queued up + * signals/console events while in the Scheduler. + * + * The original, and way hackier scheme, was to have the worker + * return a special return code representing aborted-due-to-ctrl-C-on-stdin, + * which GHC.Conc.asyncRead would look out for and retry the I/O + * call if encountered. */ - 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; + Sleep(0); + } else { + break; } + } else { + break; } + } else { + break; + } } if (len == -1) { errCode = errno; } } -- 1.7.10.4