VirtualBox

Changeset 3196 in kBuild


Ignore:
Timestamp:
Mar 27, 2018 7:47:42 PM (7 years ago)
Author:
bird
Message:

kmk/win: Suppress annoying the source filename output from CL.EXE. Fixed bug in mkWinChildcareWorkerFlushUnwritten.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kmk/w32/winchildren.c

    r3195 r3196  
    172172    /** Set if core was dumped. */
    173173    int                     fCoreDumped;
     174    /** Set if the a child process is a candidate for cl.exe where we supress
     175     * annoying source name output. */
     176    BOOL                    fProbableClExe;
    174177
    175178    /** Type specific data. */
     
    268271    /** Set if we've got a read pending already. */
    269272    BOOL                fReadPending;
     273    /** Indicator that we've written out something.  This is cleared before
     274     * we start catching output from a new child and use in the CL.exe
     275     * supression heuristics. */
     276    BOOL                fHaveWrittenOut;
    270277    /** Number of bytes at the start of the buffer that we've already
    271278     * written out.  We try write out whole lines. */
     
    641648static void mkWinChildcareWorkerFlushUnwritten(PWINCHILD pChild, PWINCCWPIPE pPipe)
    642649{
    643     DWORD cbUnwritten = pPipe->cbWritten - pPipe->offPendingRead;
     650    DWORD cbUnwritten = pPipe->offPendingRead - pPipe->cbWritten;
     651    assert(pPipe->cbWritten      <= pPipe->cbBuffer - 16);
     652    assert(pPipe->offPendingRead <= pPipe->cbBuffer - 16);
    644653    if (cbUnwritten)
    645654    {
     
    658667                pPipe->cbWritten += cbWritten <= cbUnwritten ? cbWritten : cbUnwritten; /* paranoia */
    659668        }
    660     }
     669        pPipe->fHaveWrittenOut = TRUE;
     670    }
     671}
     672
     673/**
     674 * This logic mirrors kwSandboxConsoleFlushAll.
     675 *
     676 * @returns TRUE if it looks like a CL.EXE source line, otherwise FALSE.
     677 * @param   pPipe               The pipe.
     678 * @param   offStart            The start of the output in the pipe buffer.
     679 * @param   offEnd              The end of the output in the pipe buffer.
     680 */
     681static BOOL mkWinChildcareWorkerIsClExeSourceLine(PWINCCWPIPE pPipe, DWORD offStart, DWORD offEnd)
     682{
     683    if (offEnd < offStart + 2)
     684        return FALSE;
     685    if (offEnd - offStart > 80)
     686        return FALSE;
     687
     688    if (   pPipe->pbBuffer[offEnd - 2] != '\r'
     689        || pPipe->pbBuffer[offEnd - 1] != '\n')
     690        return FALSE;
     691
     692    offEnd -= 2;
     693    while (offEnd-- > offStart)
     694    {
     695        char ch = pPipe->pbBuffer[offEnd];
     696        if (isalnum(ch) || ch == '.' || ch == ' ' || ch == '_' || ch == '-')
     697        { /* likely */ }
     698        else
     699            return FALSE;
     700    }
     701
     702    return TRUE;
    661703}
    662704
     
    675717    DWORD offStart = pPipe->cbWritten;
    676718    assert(offStart <= pPipe->offPendingRead);
     719    assert(offStart <= pPipe->cbBuffer - 16);
     720    assert(pPipe->offPendingRead <= pPipe->cbBuffer - 16);
    677721    if (cbNewData > 0)
    678722    {
     
    692736        /* If none were found and we've less than 16 bytes left in the buffer, try
    693737           find a word boundrary to flush on instead. */
    694         if (   offRest > offStart
    695             || pPipe->cbBuffer - pPipe->offPendingRead + offStart > 16)
    696         { /* likely */ }
    697         else
     738        if (   offRest <= offStart
     739            && pPipe->cbBuffer - pPipe->offPendingRead + offStart < 16)
    698740        {
    699741            offRest = pPipe->offPendingRead;
     
    704746                offRest = pPipe->offPendingRead;
    705747        }
     748        /* If this is a potential CL.EXE process, we will keep the source
     749           filename unflushed and maybe discard it at the end. */
     750        else if (   pChild->fProbableClExe
     751                 && pPipe->iWhich == 1
     752                 && offRest == pPipe->offPendingRead
     753                 && mkWinChildcareWorkerIsClExeSourceLine(pPipe, offStart, offRest))
     754            offRest = offStart;
     755
    706756        if (offRest > offStart)
    707757        {
     
    726776                }
    727777            }
     778            pPipe->fHaveWrittenOut = TRUE;
    728779        }
    729780    }
     
    745796 * @param   pChild          The child.
    746797 * @param   pPipe           The pipe.
    747  * @param   fFlushing       Set if we're flushing the pipe after the process
     798 * @param   fDraining       Set if we're draining the pipe after the process
    748799 *                          terminated.
    749800 */
    750 static void mkWinChildcareWorkerCatchOutput(PWINCHILD pChild, PWINCCWPIPE pPipe, BOOL fFlushing)
     801static void mkWinChildcareWorkerCatchOutput(PWINCHILD pChild, PWINCCWPIPE pPipe, BOOL fDraining)
    751802{
    752803    /*
     
    756807    {
    757808        DWORD cbRead = 0;
    758         if (GetOverlappedResult(pPipe->hPipeMine, &pPipe->Overlapped, &cbRead, !fFlushing))
     809        if (GetOverlappedResult(pPipe->hPipeMine, &pPipe->Overlapped, &cbRead, !fDraining))
    759810        {
    760811            mkWinChildcareWorkerCaughtMoreOutput(pChild, pPipe, cbRead);
    761812            pPipe->fReadPending = FALSE;
    762813        }
    763         else if (fFlushing && GetLastError() == ERROR_IO_INCOMPLETE)
    764         {
    765             if (pPipe->offPendingRead > pPipe->cbWritten)
    766                 mkWinChildcareWorkerFlushUnwritten(pChild, pPipe);
     814        else if (fDraining && GetLastError() == ERROR_IO_INCOMPLETE)
    767815            return;
    768         }
    769816        else
    770817        {
    771818            fprintf(stderr, "warning: GetOverlappedResult failed: %u\n", GetLastError());
    772819            pPipe->fReadPending = FALSE;
    773             if (fFlushing)
     820            if (fDraining)
    774821                return;
    775822        }
     
    807854
    808855/**
     856 * Makes sure the output pipes are drained and pushed to output.
     857 *
     858 * @param   pWorker             The worker.
     859 * @param   pChild              The child.
     860 */
     861static void mkWinChildcareWorkerDrainPipes(PWINCHILDCAREWORKER pWorker, PWINCHILD pChild)
     862{
     863    mkWinChildcareWorkerCatchOutput(pChild, &pWorker->StdOut, TRUE /*fDraining*/);
     864    mkWinChildcareWorkerCatchOutput(pChild, &pWorker->StdErr, TRUE /*fDraining*/);
     865
     866    /* Drop lone 'source.c' line from CL.exe, but only if no other output at all. */
     867    if (   pChild->fProbableClExe
     868        && !pWorker->StdOut.fHaveWrittenOut
     869        && !pWorker->StdErr.fHaveWrittenOut
     870        && pWorker->StdErr.cbWritten == pWorker->StdErr.offPendingRead
     871        && pWorker->StdOut.cbWritten < pWorker->StdOut.offPendingRead
     872        && mkWinChildcareWorkerIsClExeSourceLine(&pWorker->StdOut, pWorker->StdOut.cbWritten, pWorker->StdOut.offPendingRead))
     873    {
     874        if (!pWorker->StdOut.fReadPending)
     875            pWorker->StdOut.cbWritten = pWorker->StdOut.offPendingRead = 0;
     876        else
     877            pWorker->StdOut.cbWritten = pWorker->StdOut.offPendingRead;
     878    }
     879    else
     880    {
     881        mkWinChildcareWorkerFlushUnwritten(pChild, &pWorker->StdOut);
     882        mkWinChildcareWorkerFlushUnwritten(pChild, &pWorker->StdErr);
     883    }
     884}
     885
     886/**
    809887 * Commmon worker for waiting on a child process and retrieving the exit code.
    810888 *
     
    822900    DWORD const msStart = GetTickCount();
    823901    DWORD       msNextMsg = msStart + 15000;
     902
     903    /* Reset the written indicators on the pipes before we start loop. */
     904    pWorker->StdOut.fHaveWrittenOut = FALSE;
     905    pWorker->StdErr.fHaveWrittenOut = FALSE;
     906
    824907    for (;;)
    825908    {
     
    835918            dwStatus = WaitForMultipleObjects(3, ahHandles, FALSE /*fWaitAll*/, 1000 /*ms*/);
    836919            if (dwStatus == WAIT_OBJECT_0 + 1)
    837                 mkWinChildcareWorkerCatchOutput(pChild, &pWorker->StdOut, FALSE /*fFlushing*/);
     920                mkWinChildcareWorkerCatchOutput(pChild, &pWorker->StdOut, FALSE /*fDraining*/);
    838921            else if (dwStatus == WAIT_OBJECT_0 + 2)
    839                 mkWinChildcareWorkerCatchOutput(pChild, &pWorker->StdErr, FALSE /*fFlushing*/);
     922                mkWinChildcareWorkerCatchOutput(pChild, &pWorker->StdErr, FALSE /*fDraining*/);
    840923        }
    841924        assert(dwStatus != WAIT_FAILED);
     
    850933            {
    851934                pChild->iExitCode = (int)dwExitCode;
    852                 if (!fCatchOutput)
    853                 {
    854                     mkWinChildcareWorkerCatchOutput(pChild, &pWorker->StdOut, TRUE /*fFlushing*/);
    855                     mkWinChildcareWorkerCatchOutput(pChild, &pWorker->StdErr, TRUE /*fFlushing*/);
    856                 }
     935                if (fCatchOutput)
     936                    mkWinChildcareWorkerDrainPipes(pWorker, pChild);
    857937                return dwExitCode;
    858938            }
     
    14641544}
    14651545
     1546/**
     1547 * Checks if the image path looks like microsoft CL.exe.
     1548 *
     1549 * @returns TRUE / FALSE.
     1550 * @param   pwszImagePath   The executable image path to evalutate.
     1551 * @param   cwcImagePath    The length of the image path.
     1552 */
     1553static BOOL mkWinChildIsProbableClExe(WCHAR const *pwszImagePath, size_t cwcImagePath)
     1554{
     1555    assert(pwszImagePath[cwcImagePath] == '\0');
     1556    return cwcImagePath > 7
     1557        && (pwszImagePath[cwcImagePath - 7] == L'/' || pwszImagePath[cwcImagePath - 7] == L'\\')
     1558        && (pwszImagePath[cwcImagePath - 6] == L'c' || pwszImagePath[cwcImagePath - 6] == L'C')
     1559        && (pwszImagePath[cwcImagePath - 5] == L'l' || pwszImagePath[cwcImagePath - 5] == L'L')
     1560        &&  pwszImagePath[cwcImagePath - 4] == L'.'
     1561        && (pwszImagePath[cwcImagePath - 3] == L'e' || pwszImagePath[cwcImagePath - 3] == L'E')
     1562        && (pwszImagePath[cwcImagePath - 2] == L'x' || pwszImagePath[cwcImagePath - 2] == L'X')
     1563        && (pwszImagePath[cwcImagePath - 1] == L'e' || pwszImagePath[cwcImagePath - 1] == L'E');
     1564}
    14661565
    14671566/**
     
    14831582 *                          could be the shell.
    14841583 * @param   pfNeedShell     Where to return shell vs direct execution indicator.
     1584 * @param   pfProbableClExe Where to return an indicator of probably CL.EXE.
    14851585 */
    14861586static int mkWinChildcareWorkerFindImage(char const *pszArg0, WCHAR *pwszSearchPath, WCHAR const *pwszzEnv,
    1487                                          const char *pszShell, WCHAR **ppwszImagePath, BOOL *pfNeedShell)
     1587                                         const char *pszShell, WCHAR **ppwszImagePath, BOOL *pfNeedShell, BOOL *pfProbableClExe)
    14881588{
    14891589    /** @todo Slap a cache on this code. We usually end up executing the same
     
    15281628            *pwc++ = L'\\';
    15291629
    1530         /* Don't need to set this all the time... */
     1630        /* Don't need to set these all the time... */
    15311631        *pfNeedShell = FALSE;
     1632        *pfProbableClExe = FALSE;
    15321633
    15331634        /*
     
    15721673            if (GetFileAttributesW(pwszPath) != INVALID_FILE_ATTRIBUTES)
    15731674#endif
     1675            {
     1676                *pfProbableClExe = mkWinChildIsProbableClExe(pwszPath, cwcPath + 4 - 1);
    15741677                return mkWinChildDuplicateUtf16String(pwszPath, cwcPath + 4, ppwszImagePath);
     1678            }
    15751679
    15761680            /*
     
    15921696                        CloseHandle(hFile);
    15931697                        if (!*pfNeedShell)
     1698                        {
     1699                            *pfProbableClExe = mkWinChildIsProbableClExe(pwszPath, cwcPath - 1);
    15941700                            return mkWinChildDuplicateUtf16String(pwszPath, cwcPath, ppwszImagePath);
     1701                        }
    15951702                    }
    15961703                }
     
    17141821                        && !(dwAttribs & FILE_ATTRIBUTE_DIRECTORY))
    17151822#endif
     1823                    {
     1824                        *pfProbableClExe = mkWinChildIsProbableClExe(wszPathBuf, cwcCombined + (fHasExeSuffix ? 0 : 4) - 1);
    17161825                        return mkWinChildDuplicateUtf16String(wszPathBuf, cwcCombined + (fHasExeSuffix ? 0 : 4), ppwszImagePath);
     1826                    }
    17171827                    if (!fHasExeSuffix)
    17181828                    {
     
    17331843                                CloseHandle(hFile);
    17341844                                if (!*pfNeedShell)
     1845                                {
     1846                                    *pfProbableClExe = mkWinChildIsProbableClExe(wszPathBuf, cwcCombined - 1);
    17351847                                    return mkWinChildDuplicateUtf16String(wszPathBuf, cwcCombined, ppwszImagePath);
     1848                                }
    17361849                                break;
    17371850                            }
     
    19572070    WCHAR  *pwszImageName    = NULL;
    19582071    BOOL    fNeedShell       = FALSE;
     2072    BOOL    fProbableClExe   = FALSE;
    19592073    int     rc;
    19602074
     
    19722086    if (rc == 0)
    19732087        rc = mkWinChildcareWorkerFindImage(pChild->u.Process.papszArgs[0], pwszSearchPath, pwszzEnvironment,
    1974                                            pChild->u.Process.pszShell, &pwszImageName, &fNeedShell);
     2088                                           pChild->u.Process.pszShell, &pwszImageName, &fNeedShell, &pChild->fProbableClExe);
    19752089    if (rc == 0)
    19762090    {
     
    29283042    WCHAR              *pwszCwd          = NULL;
    29293043    BOOL                fNeedShell       = FALSE;
     3044    PWINCHILD           pChild;
    29303045    int                 rc;
    29313046    assert(pWorker->uMagic == WINCHILDCAREWORKER_MAGIC);
    2932     assert(pWorker->pCurChild != NULL && pWorker->pCurChild->uMagic == WINCHILD_MAGIC);
     3047    pChild = pWorker->pCurChild;
     3048    assert(pChild != NULL && pChild->uMagic == WINCHILD_MAGIC);
    29333049
    29343050    /*
     
    29613077     */
    29623078    if (rc == 0)
    2963         rc = mkWinChildcareWorkerFindImage(pszExecutable, pwszSearchPath, pwszzEnvironment,
    2964                                            NULL /*pszNull*/, &pwszImageName, &fNeedShell);
     3079        rc = mkWinChildcareWorkerFindImage(pszExecutable, pwszSearchPath, pwszzEnvironment, NULL /*pszShell*/,
     3080                                           &pwszImageName, &fNeedShell, &pChild->fProbableClExe);
    29653081    if (rc == 0)
    29663082    {
     
    29843100                 * Wait for the child to complete.
    29853101                 */
    2986                 rc = mkWinChildcareWorkerWaitForProcess(pWorker, pWorker->pCurChild, hProcess, pwszImageName,
    2987                                                         TRUE /*fCatchOutput*/);
     3102                rc = mkWinChildcareWorkerWaitForProcess(pWorker, pChild, hProcess, pwszImageName, TRUE /*fCatchOutput*/);
    29883103                CloseHandle(hProcess);
    29893104            }
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