VirtualBox

Changeset 3199 in kBuild


Ignore:
Timestamp:
Mar 28, 2018 6:56:21 PM (7 years ago)
Author:
bird
Message:

kmk,kWorker: Catch output from kWorker processes when --output-sync isn't 'none'.

Location:
trunk/src
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kWorker/kWorker.c

    r3198 r3199  
    928928
    929929/** Whether control-C/SIGINT or Control-Break/SIGBREAK have been seen. */
    930 static KBOOL volatile g_fCtrlC = K_FALSE;
     930static int volatile g_rcCtrlC = 0;
     931
     932/** The communication pipe handle.  We break this when we see Ctrl-C such. */
     933#ifdef KBUILD_OS_WINDOWS
     934static HANDLE       g_hPipe = INVALID_HANDLE_VALUE;
     935#else
     936static int          g_hPipe = -1;
     937#endif
     938
    931939
    932940/* Further down. */
     
    66576665    KUPTR const idxHandle = KW_HANDLE_TO_INDEX(hFile);
    66586666    g_cWriteFileCalls++;
    6659     kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread || g_fCtrlC);
     6667    kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread || g_rcCtrlC != 0);
    66606668    if (idxHandle < g_Sandbox.cHandles)
    66616669    {
     
    73687376    BOOL        fRet;
    73697377    KUPTR const idxHandle = KW_HANDLE_TO_INDEX(hObject);
    7370     kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread || g_fCtrlC);
     7378    kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread || g_rcCtrlC != 0);
    73717379    if (idxHandle < g_Sandbox.cHandles)
    73727380    {
     
    95269534KU32 const                  g_cSandboxGetProcReplacements = K_ELEMENTS(g_aSandboxGetProcReplacements);
    95279535
     9536/**
     9537 * Thread that is spawned by the first terminal kwSandboxCtrlHandler invocation.
     9538 *
     9539 * This will wait 5 second in a hope that the main thread will shut down the
     9540 * process nicly, otherwise it will terminate it forcefully.
     9541 */
     9542static DWORD WINAPI kwSandboxCtrlThreadProc(PVOID pvUser)
     9543{
     9544    int i;
     9545    for (i = 0; i < 10; i++)
     9546    {
     9547        Sleep(500);
     9548        CancelIoEx(g_hPipe, NULL);
     9549    }
     9550    TerminateProcess(GetCurrentProcess(), (int)(intptr_t)pvUser);
     9551    return -1;
     9552}
     9553
    95289554
    95299555/**
     
    95359561static BOOL WINAPI kwSandboxCtrlHandler(DWORD dwCtrlType)
    95369562{
     9563    DWORD        cbIgn;
     9564    int volatile rc; /* volatile for debugging */
     9565    int volatile rcPrev;
     9566    const char  *pszMsg;
    95379567    switch (dwCtrlType)
    95389568    {
    95399569        case CTRL_C_EVENT:
    9540             fprintf(stderr, "kWorker: Ctrl-C\n");
    9541             g_fCtrlC = K_TRUE;
    9542             exit(9);
     9570            rc = 9;
     9571            pszMsg = "kWorker: Ctrl-C\r\n";
    95439572            break;
    95449573
    95459574        case CTRL_BREAK_EVENT:
    9546             fprintf(stderr, "kWorker: Ctrl-Break\n");
    9547             g_fCtrlC = K_TRUE;
    9548             exit(10);
     9575            rc = 10;
     9576            pszMsg = "kWorker: Ctrl-Break\r\n";
    95499577            break;
    95509578
    95519579        case CTRL_CLOSE_EVENT:
    9552             fprintf(stderr, "kWorker: console closed\n");
    9553             g_fCtrlC = K_TRUE;
    9554             exit(11);
     9580            rc = 11;
     9581            pszMsg = "kWorker: console closed\r\n";
    95559582            break;
    95569583
    95579584        case CTRL_LOGOFF_EVENT:
    9558             fprintf(stderr, "kWorker: logoff event\n");
    9559             g_fCtrlC = K_TRUE;
    9560             exit(11);
     9585            rc = 11;
     9586            pszMsg = "kWorker: logoff event\r\n";
    95619587            break;
    95629588
    95639589        case CTRL_SHUTDOWN_EVENT:
    9564             fprintf(stderr, "kWorker: shutdown event\n");
    9565             g_fCtrlC = K_TRUE;
    9566             exit(11);
     9590            rc = 11;
     9591            pszMsg = "kWorker: shutdown event\r\n";
    95679592            break;
    95689593
    95699594        default:
    95709595            fprintf(stderr, "kwSandboxCtrlHandler: %#x\n", dwCtrlType);
    9571             break;
    9572     }
     9596            return TRUE;
     9597    }
     9598
     9599    /*
     9600     * Terminate the process after 5 seconds.
     9601     *
     9602     * We don't want to wait here as the console server will otherwise not
     9603     * signal the other processes in the console, which is bad for kmk as it
     9604     * will continue to forge ahead.  So, the first time we get here we start
     9605     * a thread for doing the delayed termination.
     9606     *
     9607     * If we get here a second time we just terminate the process ourselves.
     9608     *
     9609     * Note! We do no try call exit() here as it turned out to deadlock a lot
     9610     *       flusing file descriptors (stderr back when we first wrote to it).
     9611     */
     9612    rcPrev = g_rcCtrlC;
     9613    g_rcCtrlC = rc;
     9614    WriteFile(GetStdHandle(STD_ERROR_HANDLE), pszMsg, (DWORD)strlen(pszMsg), &cbIgn, NULL);
     9615    CancelIoEx(g_hPipe, NULL); /* wake up idle main thread */
     9616    if (rcPrev == 0)
     9617    {
     9618        CreateThread(NULL, 0, kwSandboxCtrlThreadProc, (void*)(intptr_t)rc, 0 /*fFlags*/, NULL);
     9619        return TRUE;
     9620    }
     9621    TerminateProcess(GetCurrentProcess(), rc);
    95739622    return TRUE;
    95749623}
     
    1060710656    KU8 const  *pbBuf  = (KU8 const *)pvBuf;
    1060810657    KU32        cbLeft = cbToWrite;
    10609     for (;;)
     10658    while (g_rcCtrlC == 0)
    1061010659    {
    1061110660        DWORD cbActuallyWritten = 0;
     
    1062710676        }
    1062810677    }
     10678    return -1;
    1062910679}
    1063010680
     
    1064610696    KU8 *pbBuf  = (KU8 *)pvBuf;
    1064710697    KU32 cbLeft = cbToRead;
    10648     for (;;)
     10698    while (g_rcCtrlC == 0)
    1064910699    {
    1065010700        DWORD cbActuallyRead = 0;
     
    1067110721        }
    1067210722    }
     10723    return -1;
    1067310724}
    1067410725
     
    1123811289                    {
    1123911290                        close(fdNul);
    11240                         kHlpAssert(GetStdHandle(STD_INPUT_HANDLE) != hPipe);
    1124111291                        hPipe = hDuplicate;
    1124211292                    }
     
    1125711307        return kwErrPrintfRc(2, "The specified --pipe %p is not a pipe handle: type %#x (last err %u)!\n",
    1125811308                             GetFileType(hPipe), GetLastError());
     11309    g_hPipe = hPipe;
    1125911310
    1126011311    /*
     
    1129611347                    /* The first string after the header is the command. */
    1129711348                    psz = (const char *)&pbMsgBuf[sizeof(cbMsg)];
    11298                     if (strcmp(psz, "JOB") == 0)
     11349                    if (   strcmp(psz, "JOB") == 0
     11350                        && g_rcCtrlC == 0)
    1129911351                    {
    1130011352                        struct
     
    1131411366                        {
    1131511367                            kwSandboxCleanupLate(&g_Sandbox);
    11316                             continue;
     11368                            if (g_rcCtrlC == 0)
     11369                                continue;
    1131711370                        }
    1131811371                    }
     
    1134711400        if (getenv("KWORKER_STATS") != NULL)
    1134811401            kwPrintStats();
    11349         return rc > 0 ? 0 : 1;
     11402        return g_rcCtrlC != 0 ? g_rcCtrlC : rc > 0 ? 0 : 1;
    1135011403    }
    1135111404}
  • trunk/src/kmk/kmkbuiltin/kSubmit.c

    r3198 r3199  
    110110    /** For overlapped read (have valid event semaphore). */
    111111    OVERLAPPED              OverlappedRead;
     112# ifdef CONFIG_NEW_WIN_CHILDREN
     113    /** Standard output catcher (reused). */
     114    PWINCCWPIPE             pStdOut;
     115    /** Standard error catcher (reused). */
     116    PWINCCWPIPE             pStdErr;
     117# endif
    112118#else
    113119    /** The socket descriptor we use to talk to the kWorker process. */
     
    424430        wchar_t             wszPipeName[128];
    425431        HANDLE              hWorkerPipe;
    426         SECURITY_ATTRIBUTES SecAttrs = { /*nLength:*/ sizeof(SecAttrs), /*pAttrs:*/ NULL, /*bInheritHandle:*/ TRUE };
    427432        int                 iProcessorGroup = -1; /** @todo determine process group. */
    428433
    429434        /*
    430          * Create the bi-directional pipe.  Worker end is marked inheritable, our end is not.
     435         * Create the bi-directional pipe with overlapping I/O enabled.
    431436         */
    432437        if (s_fDenyRemoteClients == ~(DWORD)0)
     
    441446                                       65536 /*cbInBuffer*/,
    442447                                       0 /*cMsDefaultTimeout -> 50ms*/,
    443                                        &SecAttrs /* inherit */);
     448                                       NULL /* pSecAttr - no inherit */);
    444449        if (hWorkerPipe != INVALID_HANDLE_VALUE)
    445450        {
     
    519524                        BOOL   afReplace[3] = { TRUE, FALSE, FALSE };
    520525                        HANDLE ahReplace[3] = { hWorkerPipe, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
     526                        if (pWorker->pStdOut)
     527                        {
     528                            afReplace[1] = TRUE;
     529                            afReplace[2] = TRUE;
     530                            ahReplace[1] = pWorker->pStdOut->hPipeChild;
     531                            ahReplace[2] = pWorker->pStdErr->hPipeChild;
     532                        }
     533
    521534                        rc = nt_child_inject_standard_handles(ProcInfo.hProcess, afReplace, ahReplace, szErrMsg, sizeof(szErrMsg));
    522535                        if (rc == 0)
     
    570583                    }
    571584                    else
    572                         rc = errx(pCtx, -2, "CreateProcessW failed: %u (exe=%s cmdline=%s)",
     585                        rc = errx(pCtx, -2, "CreateProcessW failed: %u (exe=%S cmdline=%S)",
    573586                                  GetLastError(), wszExecutable, wszCommandLine);
    574587                    CloseHandle(pWorker->OverlappedRead.hEvent);
     
    638651    pWorker->OverlappedRead.hEvent = INVALID_HANDLE_VALUE;
    639652
     653    if (pWorker->pStdOut)
     654        MkWinChildcareWorkerDrainPipes(NULL, pWorker->pStdOut, pWorker->pStdErr);
     655
    640656    /* It's probably shutdown already, if not give it 10 milliseconds before
    641657       we terminate it forcefully. */
     
    644660    {
    645661        BOOL fRc = TerminateProcess(pWorker->hProcess, 127);
     662
     663        if (pWorker->pStdOut)
     664            MkWinChildcareWorkerDrainPipes(NULL, pWorker->pStdOut, pWorker->pStdErr);
     665
    646666        rcWait = WaitForSingleObject(pWorker->hProcess, 100);
    647667        if (rcWait != WAIT_OBJECT_0)
    648668            warnx(pCtx, "WaitForSingleObject returns %u (and TerminateProcess %d)", rcWait, fRc);
    649669    }
     670
     671    if (pWorker->pStdOut)
     672        MkWinChildcareWorkerDrainPipes(NULL, pWorker->pStdOut, pWorker->pStdErr);
    650673
    651674    if (!CloseHandle(pWorker->hProcess))
     
    719742    pWorker = (PWORKERINSTANCE)xcalloc(sizeof(*pWorker));
    720743    pWorker->cBits = cBitsWorker;
    721     if (kSubmitSpawnWorker(pCtx, pWorker, cVerbosity) == 0)
    722     {
    723         /*
    724          * Insert it into the process ID hash table and idle list.
    725          */
    726         size_t idxHash = KWORKER_PID_HASH(pWorker->pid);
    727         pWorker->pNextPidHash = g_apPidHash[idxHash];
    728         g_apPidHash[idxHash] = pWorker;
    729 
    730         kSubmitListAppend(&g_IdleList, pWorker);
    731         return pWorker;
    732     }
     744#if defined(CONFIG_NEW_WIN_CHILDREN) && defined(KBUILD_OS_WINDOWS)
     745    if (output_sync != OUTPUT_SYNC_NONE)
     746    {
     747        pWorker->pStdOut = MkWinChildcareCreateWorkerPipe(1, g_uWorkerSeqNo << 1);
     748        pWorker->pStdErr = MkWinChildcareCreateWorkerPipe(2, g_uWorkerSeqNo << 1);
     749    }
     750    if (   output_sync == OUTPUT_SYNC_NONE
     751        || (   pWorker->pStdOut != NULL
     752            && pWorker->pStdErr != NULL))
     753#endif
     754    {
     755        if (kSubmitSpawnWorker(pCtx, pWorker, cVerbosity) == 0)
     756        {
     757            /*
     758             * Insert it into the process ID hash table and idle list.
     759             */
     760            size_t idxHash = KWORKER_PID_HASH(pWorker->pid);
     761            pWorker->pNextPidHash = g_apPidHash[idxHash];
     762            g_apPidHash[idxHash] = pWorker;
     763
     764            kSubmitListAppend(&g_IdleList, pWorker);
     765            return pWorker;
     766        }
     767    }
     768#if defined(CONFIG_NEW_WIN_CHILDREN) && defined(KBUILD_OS_WINDOWS)
     769    if (pWorker->pStdErr)
     770        MkWinChildcareDeleteWorkerPipe(pWorker->pStdErr);
     771    if (pWorker->pStdOut)
     772        MkWinChildcareDeleteWorkerPipe(pWorker->pStdOut);
     773#endif
    733774
    734775    free(pWorker);
     
    11091150        }
    11101151# else
    1111         if (MkWinChildCreateSubmit((intptr_t)pWorker->OverlappedRead.hEvent, pWorker, pPidSpawned) == 0)
     1152        if (MkWinChildCreateSubmit((intptr_t)pWorker->OverlappedRead.hEvent, pWorker,
     1153                                   pWorker->pStdOut, pWorker->pStdErr, pPidSpawned) == 0)
    11121154        { /* likely */ }
    11131155        else
  • trunk/src/kmk/w32/winchildren.c

    r3197 r3199  
    8787*   Header Files                                                                                                                 *
    8888*********************************************************************************************************************************/
     89#include <Windows.h>
     90#include <Winternl.h>
     91
    8992#include "../makeint.h"
    9093#include "../job.h"
     
    9497#include "winchildren.h"
    9598
    96 #include <Windows.h>
    97 #include <Winternl.h>
    9899#include <assert.h>
    99100#include <process.h>
     
    132133/** Pointer to a windows child process. */
    133134typedef struct WINCHILD *PWINCHILD;
     135
    134136
    135137/**
     
    250252            /** Parameter for the cleanup callback. */
    251253            void           *pvSubmitWorker;
     254            /** Standard output catching pipe. Optional. */
     255            PWINCCWPIPE     pStdOut;
     256            /** Standard error catching pipe. Optional. */
     257            PWINCCWPIPE     pStdErr;
    252258        } Submit;
    253259
     
    263269/** WINCHILD::uMagic value. */
    264270#define WINCHILD_MAGIC      0xbabebabeU
    265 
    266 /**
    267  * A childcare worker pipe.
    268  */
    269 typedef struct WINCCWPIPE
    270 {
    271     /** My end of the pipe. */
    272     HANDLE              hPipeMine;
    273     /** The child end of the pipe. */
    274     HANDLE              hPipeChild;
    275     /** The event for asynchronous reading. */
    276     HANDLE              hEvent;
    277     /** Which pipe this is (1 == stdout, 2 == stderr). */
    278     unsigned char       iWhich;
    279     /** Set if we've got a read pending already. */
    280     BOOL                fReadPending;
    281     /** Indicator that we've written out something.  This is cleared before
    282      * we start catching output from a new child and use in the CL.exe
    283      * supression heuristics. */
    284     BOOL                fHaveWrittenOut;
    285     /** Number of bytes at the start of the buffer that we've already
    286      * written out.  We try write out whole lines. */
    287     DWORD               cbWritten;
    288     /** The buffer offset of the read currently pending. */
    289     DWORD               offPendingRead;
    290     /** Read buffer size. */
    291     DWORD               cbBuffer;
    292     /** The read buffer allocation. */
    293     unsigned char      *pbBuffer;
    294     /** Overlapped I/O structure. */
    295     OVERLAPPED          Overlapped;
    296 } WINCCWPIPE;
    297 typedef WINCCWPIPE *PWINCCWPIPE;
    298271
    299272
     
    330303    HANDLE                  hEvtIdle;
    331304    /** The pipe catching standard output from a child. */
    332     WINCCWPIPE              StdOut;
     305    PWINCCWPIPE             pStdOut;
    333306    /** The pipe catching standard error from a child. */
    334     WINCCWPIPE              StdErr;
     307    PWINCCWPIPE             pStdErr;
    335308
    336309    /** Pointer to the current child. */
     
    744717    {
    745718#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
    746         if (pChild->pMkChild)
     719        if (pChild && pChild->pMkChild)
    747720        {
    748721            output_write_bin(&pChild->pMkChild->output, pPipe->iWhich == 2, &pPipe->pbBuffer[pPipe->cbWritten], cbUnwritten);
     
    799772 * reshuffle the buffer if desirable.
    800773 *
    801  * @param   pChild          The child.
     774 * @param   pChild          The child. Optional (kSubmit).
    802775 * @param   iWhich          Which standard descriptor number.
    803776 * @param   cbNewData       How much more output was caught.
     
    838811        /* If this is a potential CL.EXE process, we will keep the source
    839812           filename unflushed and maybe discard it at the end. */
    840         else if (   pChild->fProbableClExe
     813        else if (   pChild
     814                 && pChild->fProbableClExe
    841815                 && pPipe->iWhich == 1
    842816                 && offRest == pPipe->offPendingRead
     
    849823            DWORD cbToWrite = offRest - offStart;
    850824#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
    851             if (pChild->pMkChild)
     825            if (pChild && pChild->pMkChild)
    852826            {
    853827                output_write_bin(&pChild->pMkChild->output, pPipe->iWhich == 2, &pPipe->pbBuffer[offStart], cbToWrite);
     
    884858 * Catches output from the given pipe.
    885859 *
    886  * @param   pChild          The child.
     860 * @param   pChild          The child. Optional (kSubmit).
    887861 * @param   pPipe           The pipe.
    888862 * @param   fDraining       Set if we're draining the pipe after the process
     
    906880        else
    907881        {
    908             MkWinChildError(pChild->pWorker, 2, "GetOverlappedResult failed: %u\n", GetLastError());
     882            MkWinChildError(pChild ? pChild->pWorker : NULL, 2, "GetOverlappedResult failed: %u\n", GetLastError());
    909883            pPipe->fReadPending = FALSE;
    910884            if (fDraining)
     
    934908                pPipe->fReadPending = TRUE;
    935909            else
    936                 MkWinChildError(pChild->pWorker, 2, "ReadFile failed on standard %s: %u\n",
     910                MkWinChildError(pChild ? pChild->pWorker : NULL, 2,
     911                                "ReadFile failed on standard %s: %u\n",
    937912                                pPipe->iWhich == 1 ? "output" : "error",  GetLastError());
    938913            return;
     
    946921 * Makes sure the output pipes are drained and pushed to output.
    947922 *
    948  * @param   pWorker             The worker.
    949  * @param   pChild              The child.
    950  */
    951 static void mkWinChildcareWorkerDrainPipes(PWINCHILDCAREWORKER pWorker, PWINCHILD pChild)
    952 {
    953     mkWinChildcareWorkerCatchOutput(pChild, &pWorker->StdOut, TRUE /*fDraining*/);
    954     mkWinChildcareWorkerCatchOutput(pChild, &pWorker->StdErr, TRUE /*fDraining*/);
     923 * @param   pChild              The child. Optional (kSubmit).
     924 * @param   pStdOut             The standard output pipe structure.
     925 * @param   pStdErr             The standard error pipe structure.
     926 */
     927void MkWinChildcareWorkerDrainPipes(PWINCHILD pChild, PWINCCWPIPE pStdOut, PWINCCWPIPE pStdErr)
     928{
     929    mkWinChildcareWorkerCatchOutput(pChild, pStdOut, TRUE /*fDraining*/);
     930    mkWinChildcareWorkerCatchOutput(pChild, pStdErr, TRUE /*fDraining*/);
    955931
    956932    /* Drop lone 'source.c' line from CL.exe, but only if no other output at all. */
    957     if (   pChild->fProbableClExe
    958         && !pWorker->StdOut.fHaveWrittenOut
    959         && !pWorker->StdErr.fHaveWrittenOut
    960         && pWorker->StdErr.cbWritten == pWorker->StdErr.offPendingRead
    961         && pWorker->StdOut.cbWritten < pWorker->StdOut.offPendingRead
    962         && mkWinChildcareWorkerIsClExeSourceLine(&pWorker->StdOut, pWorker->StdOut.cbWritten, pWorker->StdOut.offPendingRead))
    963     {
    964         if (!pWorker->StdOut.fReadPending)
    965             pWorker->StdOut.cbWritten = pWorker->StdOut.offPendingRead = 0;
     933    if (   pChild
     934        && pChild->fProbableClExe
     935        && !pStdOut->fHaveWrittenOut
     936        && !pStdErr->fHaveWrittenOut
     937        && pStdErr->cbWritten == pStdErr->offPendingRead
     938        && pStdOut->cbWritten < pStdOut->offPendingRead
     939        && mkWinChildcareWorkerIsClExeSourceLine(pStdOut, pStdOut->cbWritten, pStdOut->offPendingRead))
     940    {
     941        if (!pStdOut->fReadPending)
     942            pStdOut->cbWritten = pStdOut->offPendingRead = 0;
    966943        else
    967             pWorker->StdOut.cbWritten = pWorker->StdOut.offPendingRead;
     944            pStdOut->cbWritten = pStdOut->offPendingRead;
    968945    }
    969946    else
    970947    {
    971         mkWinChildcareWorkerFlushUnwritten(pChild, &pWorker->StdOut);
    972         mkWinChildcareWorkerFlushUnwritten(pChild, &pWorker->StdErr);
     948        mkWinChildcareWorkerFlushUnwritten(pChild, pStdOut);
     949        mkWinChildcareWorkerFlushUnwritten(pChild, pStdErr);
    973950    }
    974951}
     
    992969
    993970    /* Reset the written indicators on the pipes before we start loop. */
    994     pWorker->StdOut.fHaveWrittenOut = FALSE;
    995     pWorker->StdErr.fHaveWrittenOut = FALSE;
     971    pWorker->pStdOut->fHaveWrittenOut = FALSE;
     972    pWorker->pStdErr->fHaveWrittenOut = FALSE;
    996973
    997974    for (;;)
     
    1005982        else
    1006983        {
    1007             HANDLE ahHandles[3] = { hProcess, pWorker->StdOut.hEvent, pWorker->StdErr.hEvent };
     984            HANDLE ahHandles[3] = { hProcess, pWorker->pStdOut->hEvent, pWorker->pStdErr->hEvent };
    1008985            dwStatus = WaitForMultipleObjects(3, ahHandles, FALSE /*fWaitAll*/, 1000 /*ms*/);
    1009986            if (dwStatus == WAIT_OBJECT_0 + 1)
    1010                 mkWinChildcareWorkerCatchOutput(pChild, &pWorker->StdOut, FALSE /*fDraining*/);
     987                mkWinChildcareWorkerCatchOutput(pChild, pWorker->pStdOut, FALSE /*fDraining*/);
    1011988            else if (dwStatus == WAIT_OBJECT_0 + 2)
    1012                 mkWinChildcareWorkerCatchOutput(pChild, &pWorker->StdErr, FALSE /*fDraining*/);
     989                mkWinChildcareWorkerCatchOutput(pChild, pWorker->pStdErr, FALSE /*fDraining*/);
    1013990        }
    1014991        assert(dwStatus != WAIT_FAILED);
     
    10241001                pChild->iExitCode = (int)dwExitCode;
    10251002                if (fCatchOutput)
    1026                     mkWinChildcareWorkerDrainPipes(pWorker, pChild);
     1003                    MkWinChildcareWorkerDrainPipes(pChild, pWorker->pStdOut, pWorker->pStdErr);
    10271004                return dwExitCode;
    10281005            }
     
    12051182                {
    12061183                    pafReplace[1] = TRUE;
    1207                     pahChild[1]   = pWorker->StdOut.hPipeChild;
     1184                    pahChild[1]   = pWorker->pStdOut->hPipeChild;
    12081185                }
    12091186                if (!pafReplace[2])
    12101187                {
    12111188                    pafReplace[2] = TRUE;
    1212                     pahChild[2]   = pWorker->StdErr.hPipeChild;
     1189                    pahChild[2]   = pWorker->pStdErr->hPipeChild;
    12131190                }
    12141191            }
     
    23092286static void mkWinChildcareWorkerThreadHandleSubmit(PWINCHILDCAREWORKER pWorker, PWINCHILD pChild)
    23102287{
    2311     void *pvSubmitWorker = pChild->u.Submit.pvSubmitWorker;
     2288    void  *pvSubmitWorker = pChild->u.Submit.pvSubmitWorker;
     2289
     2290    /*
     2291     * Prep the wait handles.
     2292     */
     2293    HANDLE ahHandles[3]   = { pChild->u.Submit.hEvent, NULL, NULL };
     2294    DWORD  cHandles       = 1;
     2295    if (pChild->u.Submit.pStdOut)
     2296    {
     2297        assert(pChild->u.Submit.pStdErr);
     2298        pChild->u.Submit.pStdOut->fHaveWrittenOut = FALSE;
     2299        ahHandles[cHandles++] = pChild->u.Submit.pStdOut->hPipeMine;
     2300        pChild->u.Submit.pStdErr->fHaveWrittenOut = FALSE;
     2301        ahHandles[cHandles++] = pChild->u.Submit.pStdErr->hPipeMine;
     2302    }
     2303
     2304    /*
     2305     * Wait loop.
     2306     */
    23122307    for (;;)
    23132308    {
    23142309        int   iExitCode = -42;
    23152310        int   iSignal   = -1;
    2316         DWORD dwStatus  = WaitForSingleObject(pChild->u.Submit.hEvent, INFINITE);
    2317         assert(dwStatus != WAIT_FAILED);
    2318 
     2311        DWORD dwStatus;
     2312        if (cHandles == 0)
     2313            dwStatus = WaitForSingleObject(ahHandles[0], INFINITE);
     2314        else
     2315        {
     2316            dwStatus = WaitForMultipleObjects(cHandles, ahHandles, FALSE /*fWaitAll*/, INFINITE);
     2317            assert(dwStatus != WAIT_FAILED);
     2318            if (dwStatus == WAIT_OBJECT_0 + 1)
     2319                mkWinChildcareWorkerCatchOutput(pChild, pChild->u.Submit.pStdOut, FALSE /*fDraining*/);
     2320            else if (dwStatus == WAIT_OBJECT_0 + 2)
     2321                mkWinChildcareWorkerCatchOutput(pChild, pChild->u.Submit.pStdErr, FALSE /*fDraining*/);
     2322        }
    23192323        if (kSubmitSubProcGetResult((intptr_t)pvSubmitWorker, &iExitCode, &iSignal) == 0)
    23202324        {
     2325            if (pChild->u.Submit.pStdOut)
     2326                MkWinChildcareWorkerDrainPipes(pChild, pChild->u.Submit.pStdOut, pChild->u.Submit.pStdErr);
     2327
    23212328            pChild->iExitCode = iExitCode;
    23222329            pChild->iSignal   = iSignal;
     
    24852492 * our end of the pipe.  Silly that they don't offer an API that does this.
    24862493 *
    2487  * @returns Success indicator.
     2494 * @returns The pipe that was created. NULL on failure.
    24882495 * @param   pPipe               The structure for the pipe.
    24892496 * @param   iWhich              Which standard descriptor this is a pipe for.
    24902497 * @param   idxWorker           The worker index.
    24912498 */
    2492 static BOOL mkWinChildcareCreateWorkerPipe(PWINCCWPIPE pPipe, unsigned iWhich, unsigned int idxWorker)
     2499PWINCCWPIPE MkWinChildcareCreateWorkerPipe(unsigned iWhich, unsigned int idxWorker)
    24932500{
    24942501    /*
     
    25342541                if (hEvent != NULL)
    25352542                {
     2543                    PWINCCWPIPE pPipe = (PWINCCWPIPE)xcalloc(sizeof(*pPipe));
    25362544                    pPipe->hPipeMine    = hPipeRead;
    25372545                    pPipe->hPipeChild   = hPipeWrite;
     
    25412549                    pPipe->cbBuffer     = cbPipe;
    25422550                    pPipe->pbBuffer     = xcalloc(cbPipe);
    2543                     return TRUE;
     2551                    return pPipe;
    25442552                }
    25452553
    25462554                CloseHandle(hPipeWrite);
    25472555                CloseHandle(hPipeRead);
    2548                 return FALSE;
     2556                return NULL;
    25492557            }
    25502558            CloseHandle(hPipeRead);
    25512559        }
    25522560    }
    2553     return FALSE;
     2561    return NULL;
    25542562}
    25552563
     
    25592567 * @param   pPipe       The pipe.
    25602568 */
    2561 static void mkWinChildcareDeleteWorkerPipe(PWINCCWPIPE pPipe)
     2569void MkWinChildcareDeleteWorkerPipe(PWINCCWPIPE pPipe)
    25622570{
    25632571    if (pPipe->hPipeChild != NULL)
     
    26022610    if (pWorker->hEvtIdle)
    26032611    {
    2604         if (mkWinChildcareCreateWorkerPipe(&pWorker->StdOut, 1, pWorker->idxWorker))
    2605         {
    2606             if (mkWinChildcareCreateWorkerPipe(&pWorker->StdErr, 2, pWorker->idxWorker))
     2612        pWorker->pStdOut = MkWinChildcareCreateWorkerPipe(1, pWorker->idxWorker);
     2613        if (pWorker->pStdOut)
     2614        {
     2615            pWorker->pStdErr = MkWinChildcareCreateWorkerPipe(2, pWorker->idxWorker);
     2616            if (pWorker->pStdErr)
    26072617            {
    26082618                /* Before we start the thread, assign it to a processor group. */
     
    26452655                /* Bail out! */
    26462656                ONS (error, NILF, "_beginthreadex failed: %u (%s)\n", errno, strerror(errno));
    2647                 mkWinChildcareDeleteWorkerPipe(&pWorker->StdErr);
     2657                MkWinChildcareDeleteWorkerPipe(pWorker->pStdErr);
    26482658            }
    26492659            else
    26502660                ON (error, NILF, "Failed to create stderr pipe: %u\n", GetLastError());
    2651             mkWinChildcareDeleteWorkerPipe(&pWorker->StdOut);
     2661            MkWinChildcareDeleteWorkerPipe(pWorker->pStdOut);
    26522662        }
    26532663        else
     
    29812991    if (CreatePipe(&hReadPipe, &hWritePipe, NULL, 0 /* default size */))
    29822992    {
    2983         if (SetHandleInformation(hWritePipe, HANDLE_FLAG_INHERIT /* clear */ , HANDLE_FLAG_INHERIT /*set*/))
     2993        //if (SetHandleInformation(hWritePipe, HANDLE_FLAG_INHERIT /* clear */ , HANDLE_FLAG_INHERIT /*set*/))
    29842994        {
    29852995            int fdReadPipe = _open_osfhandle((intptr_t)hReadPipe, O_RDONLY);
     
    30333043            ON(error, NILF, _("_open_osfhandle failed on pipe: %u\n"), errno);
    30343044        }
    3035         else
    3036             ON(error, NILF, _("SetHandleInformation failed on pipe: %u\n"), GetLastError());
     3045        //else
     3046        //    ON(error, NILF, _("SetHandleInformation failed on pipe: %u\n"), GetLastError());
    30373047        if (hReadPipe != INVALID_HANDLE_VALUE)
    30383048            CloseHandle(hReadPipe);
     
    31093119 * @param   pvSubmitWorker  The argument to pass back to kSubmit to clean up.
    31103120 * @param   pPid            Where to return the pid.
    3111  */
    3112 int MkWinChildCreateSubmit(intptr_t hEvent, void *pvSubmitWorker, pid_t *pPid)
     3121 * @param   pStdOut         Standard output pipe for the worker. Optional.
     3122 * @param   pStdErr         Standard error pipe for the worker. Optional.
     3123 */
     3124int MkWinChildCreateSubmit(intptr_t hEvent, void *pvSubmitWorker, PWINCCWPIPE pStdOut, PWINCCWPIPE pStdErr, pid_t *pPid)
    31133125{
    31143126    PWINCHILD pChild = mkWinChildNew(WINCHILDTYPE_SUBMIT);
    31153127    pChild->u.Submit.hEvent         = (HANDLE)hEvent;
    31163128    pChild->u.Submit.pvSubmitWorker = pvSubmitWorker;
     3129    pChild->u.Submit.pStdOut        = pStdOut;
     3130    pChild->u.Submit.pStdErr        = pStdErr;
    31173131    return mkWinChildPushToCareWorker(pChild, pPid);
    31183132}
  • trunk/src/kmk/w32/winchildren.h

    r3195 r3199  
    2727#define INCLUDED_WINCHILDREN_H
    2828
     29#ifdef DECLARE_HANDLE
     30/**
     31 * A childcare worker pipe.
     32 */
     33typedef struct WINCCWPIPE
     34{
     35    /** My end of the pipe. */
     36    HANDLE              hPipeMine;
     37    /** The child end of the pipe. */
     38    HANDLE              hPipeChild;
     39    /** The event for asynchronous reading. */
     40    HANDLE              hEvent;
     41    /** Which pipe this is (1 == stdout, 2 == stderr). */
     42    unsigned char       iWhich;
     43    /** Set if we've got a read pending already. */
     44    BOOL                fReadPending;
     45    /** Indicator that we've written out something.  This is cleared before
     46     * we start catching output from a new child and use in the CL.exe
     47     * supression heuristics. */
     48    BOOL                fHaveWrittenOut;
     49    /** Number of bytes at the start of the buffer that we've already
     50     * written out.  We try write out whole lines. */
     51    DWORD               cbWritten;
     52    /** The buffer offset of the read currently pending. */
     53    DWORD               offPendingRead;
     54    /** Read buffer size. */
     55    DWORD               cbBuffer;
     56    /** The read buffer allocation. */
     57    unsigned char      *pbBuffer;
     58    /** Overlapped I/O structure. */
     59    OVERLAPPED          Overlapped;
     60} WINCCWPIPE;
     61#endif
     62
     63typedef struct WINCCWPIPE *PWINCCWPIPE;
    2964
    3065void    MkWinChildInit(unsigned int cJobSlot);
     
    3974int     MkWinChildCreateAppend(const char *pszFilename, char **ppszAppend, size_t cbAppend, int fTruncate,
    4075                               struct child *pMkChild, pid_t *pPid);
    41 int     MkWinChildCreateSubmit(intptr_t hEvent, void *pvSubmitWorker, pid_t *pPid);
     76
     77int     MkWinChildCreateSubmit(intptr_t hEvent, void *pvSubmitWorker, PWINCCWPIPE pStdOut, PWINCCWPIPE pStdErr, pid_t *pPid);
     78PWINCCWPIPE MkWinChildcareCreateWorkerPipe(unsigned iWhich, unsigned int idxWorker);
     79void    MkWinChildcareWorkerDrainPipes(struct WINCHILD *pChild, PWINCCWPIPE pStdOut, PWINCCWPIPE pStdErr);
     80void    MkWinChildcareDeleteWorkerPipe(PWINCCWPIPE pPipe);
     81
    4282int     MkWinChildCreateRedirect(intptr_t hProcess, pid_t *pPid);
    4383# ifdef DECLARE_HANDLE
     
    5595int     MkWinChildUnrelatedCloseOnExec(int fd);
    5696
     97
    5798#endif
    5899
  • trunk/src/lib/nt/kFsCache.h

    r3184 r3199  
    494494 * Generic logging.
    495495 * @param a     Argument list for kFsCacheDbgPrintf  */
    496 #ifdef NDEBUG
     496#if 1 /*def NDEBUG - enable when needed! */
    497497# define KFSCACHE_LOG(a) do { } while (0)
    498498#else
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette