Changeset 3199 for trunk/src/kmk


Ignore:
Timestamp:
Mar 28, 2018, 8: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/kmk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • 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
Note: See TracChangeset for help on using the changeset viewer.