[project @ 2005-01-21 19:58:51 by sof]
authorsof <unknown>
Fri, 21 Jan 2005 19:59:01 +0000 (19:59 +0000)
committersof <unknown>
Fri, 21 Jan 2005 19:59:01 +0000 (19:59 +0000)
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
ghc/rts/win32/ConsoleHandler.c
ghc/rts/win32/IOManager.c

index 6aedb8f..76fec45 100644 (file)
@@ -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
     }
index a1d3bd9..a6a53a0 100644 (file)
@@ -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;
     }
 }
index 96e5794..60f6aa8 100644 (file)
@@ -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; }
                    }