Index: /trunk/src/kWorker/kWorker.c
===================================================================
--- /trunk/src/kWorker/kWorker.c	(revision 3198)
+++ /trunk/src/kWorker/kWorker.c	(revision 3199)
@@ -928,5 +928,13 @@
 
 /** Whether control-C/SIGINT or Control-Break/SIGBREAK have been seen. */
-static KBOOL volatile g_fCtrlC = K_FALSE;
+static int volatile g_rcCtrlC = 0;
+
+/** The communication pipe handle.  We break this when we see Ctrl-C such. */
+#ifdef KBUILD_OS_WINDOWS
+static HANDLE       g_hPipe = INVALID_HANDLE_VALUE;
+#else
+static int          g_hPipe = -1;
+#endif
+
 
 /* Further down. */
@@ -6657,5 +6665,5 @@
     KUPTR const idxHandle = KW_HANDLE_TO_INDEX(hFile);
     g_cWriteFileCalls++;
-    kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread || g_fCtrlC);
+    kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread || g_rcCtrlC != 0);
     if (idxHandle < g_Sandbox.cHandles)
     {
@@ -7368,5 +7376,5 @@
     BOOL        fRet;
     KUPTR const idxHandle = KW_HANDLE_TO_INDEX(hObject);
-    kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread || g_fCtrlC);
+    kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread || g_rcCtrlC != 0);
     if (idxHandle < g_Sandbox.cHandles)
     {
@@ -9526,4 +9534,22 @@
 KU32 const                  g_cSandboxGetProcReplacements = K_ELEMENTS(g_aSandboxGetProcReplacements);
 
+/**
+ * Thread that is spawned by the first terminal kwSandboxCtrlHandler invocation.
+ *
+ * This will wait 5 second in a hope that the main thread will shut down the
+ * process nicly, otherwise it will terminate it forcefully.
+ */
+static DWORD WINAPI kwSandboxCtrlThreadProc(PVOID pvUser)
+{
+    int i;
+    for (i = 0; i < 10; i++)
+    {
+        Sleep(500);
+        CancelIoEx(g_hPipe, NULL);
+    }
+    TerminateProcess(GetCurrentProcess(), (int)(intptr_t)pvUser);
+    return -1;
+}
+
 
 /**
@@ -9535,40 +9561,63 @@
 static BOOL WINAPI kwSandboxCtrlHandler(DWORD dwCtrlType)
 {
+    DWORD        cbIgn;
+    int volatile rc; /* volatile for debugging */
+    int volatile rcPrev;
+    const char  *pszMsg;
     switch (dwCtrlType)
     {
         case CTRL_C_EVENT:
-            fprintf(stderr, "kWorker: Ctrl-C\n");
-            g_fCtrlC = K_TRUE;
-            exit(9);
+            rc = 9;
+            pszMsg = "kWorker: Ctrl-C\r\n";
             break;
 
         case CTRL_BREAK_EVENT:
-            fprintf(stderr, "kWorker: Ctrl-Break\n");
-            g_fCtrlC = K_TRUE;
-            exit(10);
+            rc = 10;
+            pszMsg = "kWorker: Ctrl-Break\r\n";
             break;
 
         case CTRL_CLOSE_EVENT:
-            fprintf(stderr, "kWorker: console closed\n");
-            g_fCtrlC = K_TRUE;
-            exit(11);
+            rc = 11;
+            pszMsg = "kWorker: console closed\r\n";
             break;
 
         case CTRL_LOGOFF_EVENT:
-            fprintf(stderr, "kWorker: logoff event\n");
-            g_fCtrlC = K_TRUE;
-            exit(11);
+            rc = 11;
+            pszMsg = "kWorker: logoff event\r\n";
             break;
 
         case CTRL_SHUTDOWN_EVENT:
-            fprintf(stderr, "kWorker: shutdown event\n");
-            g_fCtrlC = K_TRUE;
-            exit(11);
+            rc = 11;
+            pszMsg = "kWorker: shutdown event\r\n";
             break;
 
         default:
             fprintf(stderr, "kwSandboxCtrlHandler: %#x\n", dwCtrlType);
-            break;
-    }
+            return TRUE;
+    }
+
+    /*
+     * Terminate the process after 5 seconds.
+     *
+     * We don't want to wait here as the console server will otherwise not
+     * signal the other processes in the console, which is bad for kmk as it
+     * will continue to forge ahead.  So, the first time we get here we start
+     * a thread for doing the delayed termination.
+     *
+     * If we get here a second time we just terminate the process ourselves.
+     *
+     * Note! We do no try call exit() here as it turned out to deadlock a lot
+     *       flusing file descriptors (stderr back when we first wrote to it).
+     */
+    rcPrev = g_rcCtrlC;
+    g_rcCtrlC = rc;
+    WriteFile(GetStdHandle(STD_ERROR_HANDLE), pszMsg, (DWORD)strlen(pszMsg), &cbIgn, NULL);
+    CancelIoEx(g_hPipe, NULL); /* wake up idle main thread */
+    if (rcPrev == 0)
+    {
+        CreateThread(NULL, 0, kwSandboxCtrlThreadProc, (void*)(intptr_t)rc, 0 /*fFlags*/, NULL);
+        return TRUE;
+    }
+    TerminateProcess(GetCurrentProcess(), rc);
     return TRUE;
 }
@@ -10607,5 +10656,5 @@
     KU8 const  *pbBuf  = (KU8 const *)pvBuf;
     KU32        cbLeft = cbToWrite;
-    for (;;)
+    while (g_rcCtrlC == 0)
     {
         DWORD cbActuallyWritten = 0;
@@ -10627,4 +10676,5 @@
         }
     }
+    return -1;
 }
 
@@ -10646,5 +10696,5 @@
     KU8 *pbBuf  = (KU8 *)pvBuf;
     KU32 cbLeft = cbToRead;
-    for (;;)
+    while (g_rcCtrlC == 0)
     {
         DWORD cbActuallyRead = 0;
@@ -10671,4 +10721,5 @@
         }
     }
+    return -1;
 }
 
@@ -11238,5 +11289,4 @@
                     {
                         close(fdNul);
-                        kHlpAssert(GetStdHandle(STD_INPUT_HANDLE) != hPipe);
                         hPipe = hDuplicate;
                     }
@@ -11257,4 +11307,5 @@
         return kwErrPrintfRc(2, "The specified --pipe %p is not a pipe handle: type %#x (last err %u)!\n",
                              GetFileType(hPipe), GetLastError());
+    g_hPipe = hPipe;
 
     /*
@@ -11296,5 +11347,6 @@
                     /* The first string after the header is the command. */
                     psz = (const char *)&pbMsgBuf[sizeof(cbMsg)];
-                    if (strcmp(psz, "JOB") == 0)
+                    if (   strcmp(psz, "JOB") == 0
+                        && g_rcCtrlC == 0)
                     {
                         struct
@@ -11314,5 +11366,6 @@
                         {
                             kwSandboxCleanupLate(&g_Sandbox);
-                            continue;
+                            if (g_rcCtrlC == 0)
+                                continue;
                         }
                     }
@@ -11347,5 +11400,5 @@
         if (getenv("KWORKER_STATS") != NULL)
             kwPrintStats();
-        return rc > 0 ? 0 : 1;
+        return g_rcCtrlC != 0 ? g_rcCtrlC : rc > 0 ? 0 : 1;
     }
 }
Index: /trunk/src/kmk/kmkbuiltin/kSubmit.c
===================================================================
--- /trunk/src/kmk/kmkbuiltin/kSubmit.c	(revision 3198)
+++ /trunk/src/kmk/kmkbuiltin/kSubmit.c	(revision 3199)
@@ -110,4 +110,10 @@
     /** For overlapped read (have valid event semaphore). */
     OVERLAPPED              OverlappedRead;
+# ifdef CONFIG_NEW_WIN_CHILDREN
+    /** Standard output catcher (reused). */
+    PWINCCWPIPE             pStdOut;
+    /** Standard error catcher (reused). */
+    PWINCCWPIPE             pStdErr;
+# endif
 #else
     /** The socket descriptor we use to talk to the kWorker process. */
@@ -424,9 +430,8 @@
         wchar_t             wszPipeName[128];
         HANDLE              hWorkerPipe;
-        SECURITY_ATTRIBUTES SecAttrs = { /*nLength:*/ sizeof(SecAttrs), /*pAttrs:*/ NULL, /*bInheritHandle:*/ TRUE };
         int                 iProcessorGroup = -1; /** @todo determine process group. */
 
         /*
-         * Create the bi-directional pipe.  Worker end is marked inheritable, our end is not.
+         * Create the bi-directional pipe with overlapping I/O enabled.
          */
         if (s_fDenyRemoteClients == ~(DWORD)0)
@@ -441,5 +446,5 @@
                                        65536 /*cbInBuffer*/,
                                        0 /*cMsDefaultTimeout -> 50ms*/,
-                                       &SecAttrs /* inherit */);
+                                       NULL /* pSecAttr - no inherit */);
         if (hWorkerPipe != INVALID_HANDLE_VALUE)
         {
@@ -519,4 +524,12 @@
                         BOOL   afReplace[3] = { TRUE, FALSE, FALSE };
                         HANDLE ahReplace[3] = { hWorkerPipe, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
+                        if (pWorker->pStdOut)
+                        {
+                            afReplace[1] = TRUE;
+                            afReplace[2] = TRUE;
+                            ahReplace[1] = pWorker->pStdOut->hPipeChild;
+                            ahReplace[2] = pWorker->pStdErr->hPipeChild;
+                        }
+
                         rc = nt_child_inject_standard_handles(ProcInfo.hProcess, afReplace, ahReplace, szErrMsg, sizeof(szErrMsg));
                         if (rc == 0)
@@ -570,5 +583,5 @@
                     }
                     else
-                        rc = errx(pCtx, -2, "CreateProcessW failed: %u (exe=%s cmdline=%s)",
+                        rc = errx(pCtx, -2, "CreateProcessW failed: %u (exe=%S cmdline=%S)",
                                   GetLastError(), wszExecutable, wszCommandLine);
                     CloseHandle(pWorker->OverlappedRead.hEvent);
@@ -638,4 +651,7 @@
     pWorker->OverlappedRead.hEvent = INVALID_HANDLE_VALUE;
 
+    if (pWorker->pStdOut)
+        MkWinChildcareWorkerDrainPipes(NULL, pWorker->pStdOut, pWorker->pStdErr);
+
     /* It's probably shutdown already, if not give it 10 milliseconds before
        we terminate it forcefully. */
@@ -644,8 +660,15 @@
     {
         BOOL fRc = TerminateProcess(pWorker->hProcess, 127);
+
+        if (pWorker->pStdOut)
+            MkWinChildcareWorkerDrainPipes(NULL, pWorker->pStdOut, pWorker->pStdErr);
+
         rcWait = WaitForSingleObject(pWorker->hProcess, 100);
         if (rcWait != WAIT_OBJECT_0)
             warnx(pCtx, "WaitForSingleObject returns %u (and TerminateProcess %d)", rcWait, fRc);
     }
+
+    if (pWorker->pStdOut)
+        MkWinChildcareWorkerDrainPipes(NULL, pWorker->pStdOut, pWorker->pStdErr);
 
     if (!CloseHandle(pWorker->hProcess))
@@ -719,16 +742,34 @@
     pWorker = (PWORKERINSTANCE)xcalloc(sizeof(*pWorker));
     pWorker->cBits = cBitsWorker;
-    if (kSubmitSpawnWorker(pCtx, pWorker, cVerbosity) == 0)
-    {
-        /*
-         * Insert it into the process ID hash table and idle list.
-         */
-        size_t idxHash = KWORKER_PID_HASH(pWorker->pid);
-        pWorker->pNextPidHash = g_apPidHash[idxHash];
-        g_apPidHash[idxHash] = pWorker;
-
-        kSubmitListAppend(&g_IdleList, pWorker);
-        return pWorker;
-    }
+#if defined(CONFIG_NEW_WIN_CHILDREN) && defined(KBUILD_OS_WINDOWS)
+    if (output_sync != OUTPUT_SYNC_NONE)
+    {
+        pWorker->pStdOut = MkWinChildcareCreateWorkerPipe(1, g_uWorkerSeqNo << 1);
+        pWorker->pStdErr = MkWinChildcareCreateWorkerPipe(2, g_uWorkerSeqNo << 1);
+    }
+    if (   output_sync == OUTPUT_SYNC_NONE
+        || (   pWorker->pStdOut != NULL
+            && pWorker->pStdErr != NULL))
+#endif
+    {
+        if (kSubmitSpawnWorker(pCtx, pWorker, cVerbosity) == 0)
+        {
+            /*
+             * Insert it into the process ID hash table and idle list.
+             */
+            size_t idxHash = KWORKER_PID_HASH(pWorker->pid);
+            pWorker->pNextPidHash = g_apPidHash[idxHash];
+            g_apPidHash[idxHash] = pWorker;
+
+            kSubmitListAppend(&g_IdleList, pWorker);
+            return pWorker;
+        }
+    }
+#if defined(CONFIG_NEW_WIN_CHILDREN) && defined(KBUILD_OS_WINDOWS)
+    if (pWorker->pStdErr)
+        MkWinChildcareDeleteWorkerPipe(pWorker->pStdErr);
+    if (pWorker->pStdOut)
+        MkWinChildcareDeleteWorkerPipe(pWorker->pStdOut);
+#endif
 
     free(pWorker);
@@ -1109,5 +1150,6 @@
         }
 # else
-        if (MkWinChildCreateSubmit((intptr_t)pWorker->OverlappedRead.hEvent, pWorker, pPidSpawned) == 0)
+        if (MkWinChildCreateSubmit((intptr_t)pWorker->OverlappedRead.hEvent, pWorker,
+                                   pWorker->pStdOut, pWorker->pStdErr, pPidSpawned) == 0)
         { /* likely */ }
         else
Index: /trunk/src/kmk/w32/winchildren.c
===================================================================
--- /trunk/src/kmk/w32/winchildren.c	(revision 3198)
+++ /trunk/src/kmk/w32/winchildren.c	(revision 3199)
@@ -87,4 +87,7 @@
 *   Header Files                                                                                                                 *
 *********************************************************************************************************************************/
+#include <Windows.h>
+#include <Winternl.h>
+
 #include "../makeint.h"
 #include "../job.h"
@@ -94,6 +97,4 @@
 #include "winchildren.h"
 
-#include <Windows.h>
-#include <Winternl.h>
 #include <assert.h>
 #include <process.h>
@@ -132,4 +133,5 @@
 /** Pointer to a windows child process. */
 typedef struct WINCHILD *PWINCHILD;
+
 
 /**
@@ -250,4 +252,8 @@
             /** Parameter for the cleanup callback. */
             void           *pvSubmitWorker;
+            /** Standard output catching pipe. Optional. */
+            PWINCCWPIPE     pStdOut;
+            /** Standard error catching pipe. Optional. */
+            PWINCCWPIPE     pStdErr;
         } Submit;
 
@@ -263,37 +269,4 @@
 /** WINCHILD::uMagic value. */
 #define WINCHILD_MAGIC      0xbabebabeU
-
-/**
- * A childcare worker pipe.
- */
-typedef struct WINCCWPIPE
-{
-    /** My end of the pipe. */
-    HANDLE              hPipeMine;
-    /** The child end of the pipe. */
-    HANDLE              hPipeChild;
-    /** The event for asynchronous reading. */
-    HANDLE              hEvent;
-    /** Which pipe this is (1 == stdout, 2 == stderr). */
-    unsigned char       iWhich;
-    /** Set if we've got a read pending already. */
-    BOOL                fReadPending;
-    /** Indicator that we've written out something.  This is cleared before
-     * we start catching output from a new child and use in the CL.exe
-     * supression heuristics. */
-    BOOL                fHaveWrittenOut;
-    /** Number of bytes at the start of the buffer that we've already
-     * written out.  We try write out whole lines. */
-    DWORD               cbWritten;
-    /** The buffer offset of the read currently pending. */
-    DWORD               offPendingRead;
-    /** Read buffer size. */
-    DWORD               cbBuffer;
-    /** The read buffer allocation. */
-    unsigned char      *pbBuffer;
-    /** Overlapped I/O structure. */
-    OVERLAPPED          Overlapped;
-} WINCCWPIPE;
-typedef WINCCWPIPE *PWINCCWPIPE;
 
 
@@ -330,7 +303,7 @@
     HANDLE                  hEvtIdle;
     /** The pipe catching standard output from a child. */
-    WINCCWPIPE              StdOut;
+    PWINCCWPIPE             pStdOut;
     /** The pipe catching standard error from a child. */
-    WINCCWPIPE              StdErr;
+    PWINCCWPIPE             pStdErr;
 
     /** Pointer to the current child. */
@@ -744,5 +717,5 @@
     {
 #ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
-        if (pChild->pMkChild)
+        if (pChild && pChild->pMkChild)
         {
             output_write_bin(&pChild->pMkChild->output, pPipe->iWhich == 2, &pPipe->pbBuffer[pPipe->cbWritten], cbUnwritten);
@@ -799,5 +772,5 @@
  * reshuffle the buffer if desirable.
  *
- * @param   pChild          The child.
+ * @param   pChild          The child. Optional (kSubmit).
  * @param   iWhich          Which standard descriptor number.
  * @param   cbNewData       How much more output was caught.
@@ -838,5 +811,6 @@
         /* If this is a potential CL.EXE process, we will keep the source
            filename unflushed and maybe discard it at the end. */
-        else if (   pChild->fProbableClExe
+        else if (   pChild
+                 && pChild->fProbableClExe
                  && pPipe->iWhich == 1
                  && offRest == pPipe->offPendingRead
@@ -849,5 +823,5 @@
             DWORD cbToWrite = offRest - offStart;
 #ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
-            if (pChild->pMkChild)
+            if (pChild && pChild->pMkChild)
             {
                 output_write_bin(&pChild->pMkChild->output, pPipe->iWhich == 2, &pPipe->pbBuffer[offStart], cbToWrite);
@@ -884,5 +858,5 @@
  * Catches output from the given pipe.
  *
- * @param   pChild          The child.
+ * @param   pChild          The child. Optional (kSubmit).
  * @param   pPipe           The pipe.
  * @param   fDraining       Set if we're draining the pipe after the process
@@ -906,5 +880,5 @@
         else
         {
-            MkWinChildError(pChild->pWorker, 2, "GetOverlappedResult failed: %u\n", GetLastError());
+            MkWinChildError(pChild ? pChild->pWorker : NULL, 2, "GetOverlappedResult failed: %u\n", GetLastError());
             pPipe->fReadPending = FALSE;
             if (fDraining)
@@ -934,5 +908,6 @@
                 pPipe->fReadPending = TRUE;
             else
-                MkWinChildError(pChild->pWorker, 2, "ReadFile failed on standard %s: %u\n",
+                MkWinChildError(pChild ? pChild->pWorker : NULL, 2,
+                                "ReadFile failed on standard %s: %u\n",
                                 pPipe->iWhich == 1 ? "output" : "error",  GetLastError());
             return;
@@ -946,29 +921,31 @@
  * Makes sure the output pipes are drained and pushed to output.
  *
- * @param   pWorker             The worker.
- * @param   pChild              The child.
- */
-static void mkWinChildcareWorkerDrainPipes(PWINCHILDCAREWORKER pWorker, PWINCHILD pChild)
-{
-    mkWinChildcareWorkerCatchOutput(pChild, &pWorker->StdOut, TRUE /*fDraining*/);
-    mkWinChildcareWorkerCatchOutput(pChild, &pWorker->StdErr, TRUE /*fDraining*/);
+ * @param   pChild              The child. Optional (kSubmit).
+ * @param   pStdOut             The standard output pipe structure.
+ * @param   pStdErr             The standard error pipe structure.
+ */
+void MkWinChildcareWorkerDrainPipes(PWINCHILD pChild, PWINCCWPIPE pStdOut, PWINCCWPIPE pStdErr)
+{
+    mkWinChildcareWorkerCatchOutput(pChild, pStdOut, TRUE /*fDraining*/);
+    mkWinChildcareWorkerCatchOutput(pChild, pStdErr, TRUE /*fDraining*/);
 
     /* Drop lone 'source.c' line from CL.exe, but only if no other output at all. */
-    if (   pChild->fProbableClExe
-        && !pWorker->StdOut.fHaveWrittenOut
-        && !pWorker->StdErr.fHaveWrittenOut
-        && pWorker->StdErr.cbWritten == pWorker->StdErr.offPendingRead
-        && pWorker->StdOut.cbWritten < pWorker->StdOut.offPendingRead
-        && mkWinChildcareWorkerIsClExeSourceLine(&pWorker->StdOut, pWorker->StdOut.cbWritten, pWorker->StdOut.offPendingRead))
-    {
-        if (!pWorker->StdOut.fReadPending)
-            pWorker->StdOut.cbWritten = pWorker->StdOut.offPendingRead = 0;
+    if (   pChild
+        && pChild->fProbableClExe
+        && !pStdOut->fHaveWrittenOut
+        && !pStdErr->fHaveWrittenOut
+        && pStdErr->cbWritten == pStdErr->offPendingRead
+        && pStdOut->cbWritten < pStdOut->offPendingRead
+        && mkWinChildcareWorkerIsClExeSourceLine(pStdOut, pStdOut->cbWritten, pStdOut->offPendingRead))
+    {
+        if (!pStdOut->fReadPending)
+            pStdOut->cbWritten = pStdOut->offPendingRead = 0;
         else
-            pWorker->StdOut.cbWritten = pWorker->StdOut.offPendingRead;
+            pStdOut->cbWritten = pStdOut->offPendingRead;
     }
     else
     {
-        mkWinChildcareWorkerFlushUnwritten(pChild, &pWorker->StdOut);
-        mkWinChildcareWorkerFlushUnwritten(pChild, &pWorker->StdErr);
+        mkWinChildcareWorkerFlushUnwritten(pChild, pStdOut);
+        mkWinChildcareWorkerFlushUnwritten(pChild, pStdErr);
     }
 }
@@ -992,6 +969,6 @@
 
     /* Reset the written indicators on the pipes before we start loop. */
-    pWorker->StdOut.fHaveWrittenOut = FALSE;
-    pWorker->StdErr.fHaveWrittenOut = FALSE;
+    pWorker->pStdOut->fHaveWrittenOut = FALSE;
+    pWorker->pStdErr->fHaveWrittenOut = FALSE;
 
     for (;;)
@@ -1005,10 +982,10 @@
         else
         {
-            HANDLE ahHandles[3] = { hProcess, pWorker->StdOut.hEvent, pWorker->StdErr.hEvent };
+            HANDLE ahHandles[3] = { hProcess, pWorker->pStdOut->hEvent, pWorker->pStdErr->hEvent };
             dwStatus = WaitForMultipleObjects(3, ahHandles, FALSE /*fWaitAll*/, 1000 /*ms*/);
             if (dwStatus == WAIT_OBJECT_0 + 1)
-                mkWinChildcareWorkerCatchOutput(pChild, &pWorker->StdOut, FALSE /*fDraining*/);
+                mkWinChildcareWorkerCatchOutput(pChild, pWorker->pStdOut, FALSE /*fDraining*/);
             else if (dwStatus == WAIT_OBJECT_0 + 2)
-                mkWinChildcareWorkerCatchOutput(pChild, &pWorker->StdErr, FALSE /*fDraining*/);
+                mkWinChildcareWorkerCatchOutput(pChild, pWorker->pStdErr, FALSE /*fDraining*/);
         }
         assert(dwStatus != WAIT_FAILED);
@@ -1024,5 +1001,5 @@
                 pChild->iExitCode = (int)dwExitCode;
                 if (fCatchOutput)
-                    mkWinChildcareWorkerDrainPipes(pWorker, pChild);
+                    MkWinChildcareWorkerDrainPipes(pChild, pWorker->pStdOut, pWorker->pStdErr);
                 return dwExitCode;
             }
@@ -1205,10 +1182,10 @@
                 {
                     pafReplace[1] = TRUE;
-                    pahChild[1]   = pWorker->StdOut.hPipeChild;
+                    pahChild[1]   = pWorker->pStdOut->hPipeChild;
                 }
                 if (!pafReplace[2])
                 {
                     pafReplace[2] = TRUE;
-                    pahChild[2]   = pWorker->StdErr.hPipeChild;
+                    pahChild[2]   = pWorker->pStdErr->hPipeChild;
                 }
             }
@@ -2309,14 +2286,44 @@
 static void mkWinChildcareWorkerThreadHandleSubmit(PWINCHILDCAREWORKER pWorker, PWINCHILD pChild)
 {
-    void *pvSubmitWorker = pChild->u.Submit.pvSubmitWorker;
+    void  *pvSubmitWorker = pChild->u.Submit.pvSubmitWorker;
+
+    /*
+     * Prep the wait handles.
+     */
+    HANDLE ahHandles[3]   = { pChild->u.Submit.hEvent, NULL, NULL };
+    DWORD  cHandles       = 1;
+    if (pChild->u.Submit.pStdOut)
+    {
+        assert(pChild->u.Submit.pStdErr);
+        pChild->u.Submit.pStdOut->fHaveWrittenOut = FALSE;
+        ahHandles[cHandles++] = pChild->u.Submit.pStdOut->hPipeMine;
+        pChild->u.Submit.pStdErr->fHaveWrittenOut = FALSE;
+        ahHandles[cHandles++] = pChild->u.Submit.pStdErr->hPipeMine;
+    }
+
+    /*
+     * Wait loop.
+     */
     for (;;)
     {
         int   iExitCode = -42;
         int   iSignal   = -1;
-        DWORD dwStatus  = WaitForSingleObject(pChild->u.Submit.hEvent, INFINITE);
-        assert(dwStatus != WAIT_FAILED);
-
+        DWORD dwStatus;
+        if (cHandles == 0)
+            dwStatus = WaitForSingleObject(ahHandles[0], INFINITE);
+        else
+        {
+            dwStatus = WaitForMultipleObjects(cHandles, ahHandles, FALSE /*fWaitAll*/, INFINITE);
+            assert(dwStatus != WAIT_FAILED);
+            if (dwStatus == WAIT_OBJECT_0 + 1)
+                mkWinChildcareWorkerCatchOutput(pChild, pChild->u.Submit.pStdOut, FALSE /*fDraining*/);
+            else if (dwStatus == WAIT_OBJECT_0 + 2)
+                mkWinChildcareWorkerCatchOutput(pChild, pChild->u.Submit.pStdErr, FALSE /*fDraining*/);
+        }
         if (kSubmitSubProcGetResult((intptr_t)pvSubmitWorker, &iExitCode, &iSignal) == 0)
         {
+            if (pChild->u.Submit.pStdOut)
+                MkWinChildcareWorkerDrainPipes(pChild, pChild->u.Submit.pStdOut, pChild->u.Submit.pStdErr);
+
             pChild->iExitCode = iExitCode;
             pChild->iSignal   = iSignal;
@@ -2485,10 +2492,10 @@
  * our end of the pipe.  Silly that they don't offer an API that does this.
  *
- * @returns Success indicator.
+ * @returns The pipe that was created. NULL on failure.
  * @param   pPipe               The structure for the pipe.
  * @param   iWhich              Which standard descriptor this is a pipe for.
  * @param   idxWorker           The worker index.
  */
-static BOOL mkWinChildcareCreateWorkerPipe(PWINCCWPIPE pPipe, unsigned iWhich, unsigned int idxWorker)
+PWINCCWPIPE MkWinChildcareCreateWorkerPipe(unsigned iWhich, unsigned int idxWorker)
 {
     /*
@@ -2534,4 +2541,5 @@
                 if (hEvent != NULL)
                 {
+                    PWINCCWPIPE pPipe = (PWINCCWPIPE)xcalloc(sizeof(*pPipe));
                     pPipe->hPipeMine    = hPipeRead;
                     pPipe->hPipeChild   = hPipeWrite;
@@ -2541,15 +2549,15 @@
                     pPipe->cbBuffer     = cbPipe;
                     pPipe->pbBuffer     = xcalloc(cbPipe);
-                    return TRUE;
+                    return pPipe;
                 }
 
                 CloseHandle(hPipeWrite);
                 CloseHandle(hPipeRead);
-                return FALSE;
+                return NULL;
             }
             CloseHandle(hPipeRead);
         }
     }
-    return FALSE;
+    return NULL;
 }
 
@@ -2559,5 +2567,5 @@
  * @param   pPipe       The pipe.
  */
-static void mkWinChildcareDeleteWorkerPipe(PWINCCWPIPE pPipe)
+void MkWinChildcareDeleteWorkerPipe(PWINCCWPIPE pPipe)
 {
     if (pPipe->hPipeChild != NULL)
@@ -2602,7 +2610,9 @@
     if (pWorker->hEvtIdle)
     {
-        if (mkWinChildcareCreateWorkerPipe(&pWorker->StdOut, 1, pWorker->idxWorker))
-        {
-            if (mkWinChildcareCreateWorkerPipe(&pWorker->StdErr, 2, pWorker->idxWorker))
+        pWorker->pStdOut = MkWinChildcareCreateWorkerPipe(1, pWorker->idxWorker);
+        if (pWorker->pStdOut)
+        {
+            pWorker->pStdErr = MkWinChildcareCreateWorkerPipe(2, pWorker->idxWorker);
+            if (pWorker->pStdErr)
             {
                 /* Before we start the thread, assign it to a processor group. */
@@ -2645,9 +2655,9 @@
                 /* Bail out! */
                 ONS (error, NILF, "_beginthreadex failed: %u (%s)\n", errno, strerror(errno));
-                mkWinChildcareDeleteWorkerPipe(&pWorker->StdErr);
+                MkWinChildcareDeleteWorkerPipe(pWorker->pStdErr);
             }
             else
                 ON (error, NILF, "Failed to create stderr pipe: %u\n", GetLastError());
-            mkWinChildcareDeleteWorkerPipe(&pWorker->StdOut);
+            MkWinChildcareDeleteWorkerPipe(pWorker->pStdOut);
         }
         else
@@ -2981,5 +2991,5 @@
     if (CreatePipe(&hReadPipe, &hWritePipe, NULL, 0 /* default size */))
     {
-        if (SetHandleInformation(hWritePipe, HANDLE_FLAG_INHERIT /* clear */ , HANDLE_FLAG_INHERIT /*set*/))
+        //if (SetHandleInformation(hWritePipe, HANDLE_FLAG_INHERIT /* clear */ , HANDLE_FLAG_INHERIT /*set*/))
         {
             int fdReadPipe = _open_osfhandle((intptr_t)hReadPipe, O_RDONLY);
@@ -3033,6 +3043,6 @@
             ON(error, NILF, _("_open_osfhandle failed on pipe: %u\n"), errno);
         }
-        else
-            ON(error, NILF, _("SetHandleInformation failed on pipe: %u\n"), GetLastError());
+        //else
+        //    ON(error, NILF, _("SetHandleInformation failed on pipe: %u\n"), GetLastError());
         if (hReadPipe != INVALID_HANDLE_VALUE)
             CloseHandle(hReadPipe);
@@ -3109,10 +3119,14 @@
  * @param   pvSubmitWorker  The argument to pass back to kSubmit to clean up.
  * @param   pPid            Where to return the pid.
- */
-int MkWinChildCreateSubmit(intptr_t hEvent, void *pvSubmitWorker, pid_t *pPid)
+ * @param   pStdOut         Standard output pipe for the worker. Optional.
+ * @param   pStdErr         Standard error pipe for the worker. Optional.
+ */
+int MkWinChildCreateSubmit(intptr_t hEvent, void *pvSubmitWorker, PWINCCWPIPE pStdOut, PWINCCWPIPE pStdErr, pid_t *pPid)
 {
     PWINCHILD pChild = mkWinChildNew(WINCHILDTYPE_SUBMIT);
     pChild->u.Submit.hEvent         = (HANDLE)hEvent;
     pChild->u.Submit.pvSubmitWorker = pvSubmitWorker;
+    pChild->u.Submit.pStdOut        = pStdOut;
+    pChild->u.Submit.pStdErr        = pStdErr;
     return mkWinChildPushToCareWorker(pChild, pPid);
 }
Index: /trunk/src/kmk/w32/winchildren.h
===================================================================
--- /trunk/src/kmk/w32/winchildren.h	(revision 3198)
+++ /trunk/src/kmk/w32/winchildren.h	(revision 3199)
@@ -27,4 +27,39 @@
 #define INCLUDED_WINCHILDREN_H
 
+#ifdef DECLARE_HANDLE
+/**
+ * A childcare worker pipe.
+ */
+typedef struct WINCCWPIPE
+{
+    /** My end of the pipe. */
+    HANDLE              hPipeMine;
+    /** The child end of the pipe. */
+    HANDLE              hPipeChild;
+    /** The event for asynchronous reading. */
+    HANDLE              hEvent;
+    /** Which pipe this is (1 == stdout, 2 == stderr). */
+    unsigned char       iWhich;
+    /** Set if we've got a read pending already. */
+    BOOL                fReadPending;
+    /** Indicator that we've written out something.  This is cleared before
+     * we start catching output from a new child and use in the CL.exe
+     * supression heuristics. */
+    BOOL                fHaveWrittenOut;
+    /** Number of bytes at the start of the buffer that we've already
+     * written out.  We try write out whole lines. */
+    DWORD               cbWritten;
+    /** The buffer offset of the read currently pending. */
+    DWORD               offPendingRead;
+    /** Read buffer size. */
+    DWORD               cbBuffer;
+    /** The read buffer allocation. */
+    unsigned char      *pbBuffer;
+    /** Overlapped I/O structure. */
+    OVERLAPPED          Overlapped;
+} WINCCWPIPE;
+#endif
+
+typedef struct WINCCWPIPE *PWINCCWPIPE;
 
 void    MkWinChildInit(unsigned int cJobSlot);
@@ -39,5 +74,10 @@
 int     MkWinChildCreateAppend(const char *pszFilename, char **ppszAppend, size_t cbAppend, int fTruncate,
                                struct child *pMkChild, pid_t *pPid);
-int     MkWinChildCreateSubmit(intptr_t hEvent, void *pvSubmitWorker, pid_t *pPid);
+
+int     MkWinChildCreateSubmit(intptr_t hEvent, void *pvSubmitWorker, PWINCCWPIPE pStdOut, PWINCCWPIPE pStdErr, pid_t *pPid);
+PWINCCWPIPE MkWinChildcareCreateWorkerPipe(unsigned iWhich, unsigned int idxWorker);
+void    MkWinChildcareWorkerDrainPipes(struct WINCHILD *pChild, PWINCCWPIPE pStdOut, PWINCCWPIPE pStdErr);
+void    MkWinChildcareDeleteWorkerPipe(PWINCCWPIPE pPipe);
+
 int     MkWinChildCreateRedirect(intptr_t hProcess, pid_t *pPid);
 # ifdef DECLARE_HANDLE
@@ -55,4 +95,5 @@
 int     MkWinChildUnrelatedCloseOnExec(int fd);
 
+
 #endif
 
Index: /trunk/src/lib/nt/kFsCache.h
===================================================================
--- /trunk/src/lib/nt/kFsCache.h	(revision 3198)
+++ /trunk/src/lib/nt/kFsCache.h	(revision 3199)
@@ -494,5 +494,5 @@
  * Generic logging.
  * @param a     Argument list for kFsCacheDbgPrintf  */
-#ifdef NDEBUG
+#if 1 /*def NDEBUG - enable when needed! */
 # define KFSCACHE_LOG(a) do { } while (0)
 #else
