Ignore:
Timestamp:
Mar 16, 2020, 3:31:38 AM (5 years ago)
Author:
bird
Message:

kmk,kWorker: Assign processor groups to kWorker processes. Added --special-env hack for having a mspdbsrv.exe instance per processor group (using _MSPDBSRV_ENDPOINT_). This was complicated by PCH requiring to share .pdb file and therefore mspdbsrv.exe instance, requiring a mspdb100.dll re-init hack to disconnect kWorker from the previous mspdbsrv when switching. fun.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kmk/kmkbuiltin/kSubmit.c

    r3224 r3313  
    121121    int                     fdSocket;
    122122#endif
     123
     124    /** Current history index (must mod with aHistory element count). */
     125    unsigned                iHistory;
     126    /** History.   */
     127    struct
     128    {
     129        /** Pointer to the message, NULL if none. */
     130        void               *pvMsg;
     131        /** The message size, zero if not present. */
     132        size_t              cbMsg;
     133    } aHistory[4];
    123134
    124135    /** What it's busy with.  NULL if idle. */
     
    181192
    182193#ifdef KBUILD_OS_WINDOWS
     194/** The processor group allocator state. */
     195static MKWINCHILDCPUGROUPALLOCSTATE g_SubmitProcessorGroupAllocator;
     196# if K_ARCH_BITS == 64
     197/** The processor group allocator state for 32-bit processes. */
     198static MKWINCHILDCPUGROUPALLOCSTATE g_SubmitProcessorGroupAllocator32;
     199# endif
     200#endif
     201
     202#ifdef KBUILD_OS_WINDOWS
    183203/** Pointer to kernel32!SetThreadGroupAffinity. */
    184204static BOOL (WINAPI *g_pfnSetThreadGroupAffinity)(HANDLE, const GROUP_AFFINITY*, GROUP_AFFINITY *);
     
    428448    {
    429449#ifdef KBUILD_OS_WINDOWS
    430         static DWORD        s_fDenyRemoteClients = ~(DWORD)0;
    431         wchar_t             wszPipeName[128];
    432         HANDLE              hWorkerPipe;
    433         int                 iProcessorGroup = -1; /** @todo determine process group. */
     450        static DWORD    s_fDenyRemoteClients = ~(DWORD)0;
     451        wchar_t         wszPipeName[128];
     452        HANDLE          hWorkerPipe;
     453        int             iProcessorGroup;
     454
     455# if K_ARCH_BITS == 64
     456        /** @todo make it return -1 if not applicable (e.g only one group).  */
     457        if (pWorker->cBits != 32)
     458            iProcessorGroup = MkWinChildAllocateCpuGroup(&g_SubmitProcessorGroupAllocator);
     459        else
     460            iProcessorGroup = MkWinChildAllocateCpuGroup(&g_SubmitProcessorGroupAllocator32);
     461# else
     462        iProcessorGroup = MkWinChildAllocateCpuGroup(&g_SubmitProcessorGroupAllocator);
     463# endif
    434464
    435465        /*
     
    464494                {
    465495                    extern int          process_priority; /* main.c */
    466                     wchar_t             wszCommandLine[MAX_PATH * 3];
     496                    wchar_t             wszCommandLine[MAX_PATH * 3 + 32];
    467497                    wchar_t            *pwszDst = wszCommandLine;
    468498                    size_t              cwcDst = K_ELEMENTS(wszCommandLine);
     
    490520                        cwcDst  -= cwc;
    491521                    }
     522                    if (iProcessorGroup >= 0)
     523                    {
     524                        cwc = _snwprintf(pwszDst, cwcDst, L" --group %d", iProcessorGroup);
     525                        assert(cwc > 0 && cwc < cwcDst);
     526                        pwszDst += cwc;
     527                        cwcDst  -= cwc;
     528                    }
    492529                    *pwszDst = '\0';
    493530
     
    549586                                warnx(pCtx, "warning: failed to set kWorker thread priority: %u\n", GetLastError());
    550587
    551                             if (iProcessorGroup >= 0)
     588                            if (iProcessorGroup >= 0 && g_pfnSetThreadGroupAffinity)
    552589                            {
    553590                                GROUP_AFFINITY NewAff = { ~(uintptr_t)0, (WORD)iProcessorGroup, 0, 0, 0 };
     
    789826 * @param   fWatcomBrainDamage  The wcc/wcc386 workaround.
    790827 * @param   fNoPchCaching       Whether to disable precompiled header caching.
     828 * @param   pszSpecialEnv       Environment variable (name=value) subject to
     829 *                              special expansion in kWorker.  NULL if none.
    791830 * @param   papszPostCmdArgs    The post command and it's arguments.
    792831 * @param   cPostCmdArgs        Number of post command argument, including the
     
    795834 */
    796835static void *kSubmitComposeJobMessage(const char *pszExecutable, char **papszArgs, char **papszEnvVars,
    797                                       const char *pszCwd, int fWatcomBrainDamage, int fNoPchCaching,
     836                                      const char *pszCwd, int fWatcomBrainDamage, int fNoPchCaching, const char *pszSpecialEnv,
    798837                                      char **papszPostCmdArgs, uint32_t cPostCmdArgs, uint32_t *pcbMsg)
    799838{
    800839    size_t   cbTmp;
     840    size_t   cbSpecialEnv;
    801841    uint32_t i;
    802842    uint32_t cbMsg;
     
    833873    cbMsg += 1; /* fNoPchCaching */
    834874
     875    cbSpecialEnv = pszSpecialEnv ? strchr(pszSpecialEnv, '=') - pszSpecialEnv : 0;
     876    cbMsg += cbSpecialEnv + 1;
     877
    835878    cbMsg += sizeof(cPostCmdArgs);
    836879    for (i = 0; i < cPostCmdArgs; i++)
     
    858901    pbCursor += cbTmp;
    859902
    860     /* argument */
     903    /* arguments */
    861904    memcpy(pbCursor, &cArgs, sizeof(cArgs));
    862905    pbCursor += sizeof(cArgs);
     
    884927    *pbCursor++ = fWatcomBrainDamage != 0;
    885928    *pbCursor++ = fNoPchCaching != 0;
     929
     930    /* Special environment variable name. */
     931    memcpy(pbCursor, pszSpecialEnv, cbSpecialEnv);
     932    pbCursor += cbSpecialEnv;
     933    *pbCursor++ = '\0';
    886934
    887935    /* post command */
     
    11081156#endif /* KBUILD_OS_WINDOWS */
    11091157
     1158
     1159/**
     1160 * Adds the given message to the history.
     1161 *
     1162 * @returns Pointer to old message, or NULL if no old msg to free.
     1163 * @param   pWorker             The worker instance.
     1164 * @param   pvMsg               The message.
     1165 * @param   cbMsg               The message size.
     1166 */
     1167static void *kSubmitUpdateHistory(PWORKERINSTANCE pWorker, void *pvMsg, size_t cbMsg)
     1168{
     1169    unsigned iHistory = pWorker->iHistory % K_ELEMENTS(pWorker->aHistory);
     1170    void    *pvRet;
     1171    pWorker->iHistory++;
     1172    pvRet = pWorker->aHistory[iHistory].pvMsg;
     1173    pWorker->aHistory[iHistory].pvMsg = pvMsg;
     1174    pWorker->aHistory[iHistory].cbMsg = cbMsg;
     1175    return pvRet;
     1176}
     1177
     1178typedef struct HISTORYDUMPBUF
     1179{
     1180    char           *pszBuf;
     1181    size_t          cbBuf;
     1182    size_t          off;
     1183    PKMKBUILTINCTX  pCtx;
     1184} HISTORYDUMPBUF;
     1185
     1186
     1187static void kSubmitDumpHistoryWrite(HISTORYDUMPBUF *pBuf, const char *pch, size_t cch)
     1188{
     1189    if (pBuf->off + cch >= pBuf->cbBuf)
     1190    {
     1191        size_t cbNew = pBuf->cbBuf ? pBuf->cbBuf * 2 : 65536;
     1192        while (pBuf->off + cch >= cbNew)
     1193            cbNew *= 2;
     1194        pBuf->pszBuf = (char *)xrealloc(pBuf->pszBuf, cbNew);
     1195        pBuf->cbBuf = cbNew;
     1196    }
     1197
     1198    memcpy(&pBuf->pszBuf[pBuf->off], pch, cch);
     1199    pBuf->off += cch;
     1200    pBuf->pszBuf[pBuf->off] = '\0';
     1201}
     1202
     1203static void kSubmitDumpHistoryPrintf(HISTORYDUMPBUF *pBuf, const char *pszFormat, ...)
     1204{
     1205    char szTmp[32];
     1206    va_list va;
     1207    va_start(va, pszFormat);
     1208    for (;;)
     1209    {
     1210        const char *pszPct = strchr(pszFormat, '%');
     1211        if (!pszPct)
     1212        {
     1213            kSubmitDumpHistoryWrite(pBuf, pszFormat, strlen(pszFormat));
     1214            return;
     1215        }
     1216        if (pszPct != pszFormat)
     1217        {
     1218            kSubmitDumpHistoryWrite(pBuf, pszFormat, pszPct - pszFormat);
     1219            pszFormat = pszPct;
     1220        }
     1221        pszFormat++;
     1222        switch (*pszFormat++)
     1223        {
     1224            case 's':
     1225            {
     1226                const char * const psz = va_arg(va, const char *);
     1227                size_t const       cch = strlen(psz);
     1228                if (memchr(psz, '\'', cch))
     1229                {
     1230                    kSubmitDumpHistoryWrite(pBuf, TUPLE("\"")); /** @todo what if there are '"' in the string? */
     1231                    kSubmitDumpHistoryWrite(pBuf, psz, cch);
     1232                    kSubmitDumpHistoryWrite(pBuf, TUPLE("\""));
     1233                }
     1234                else if (   !memchr(psz, ' ', cch)
     1235                         && !memchr(psz, '\t', cch)
     1236                         && !memchr(psz, '\n', cch)
     1237                         && !memchr(psz, '\r', cch)
     1238                         && !memchr(psz, '&', cch)
     1239                         && !memchr(psz, ';', cch)
     1240                         && !memchr(psz, '|', cch))
     1241                    kSubmitDumpHistoryWrite(pBuf, psz, cch);
     1242                else
     1243                {
     1244                    kSubmitDumpHistoryWrite(pBuf, TUPLE("'"));
     1245                    kSubmitDumpHistoryWrite(pBuf, psz, strlen(psz));
     1246                    kSubmitDumpHistoryWrite(pBuf, TUPLE("'"));
     1247                }
     1248                break;
     1249            }
     1250
     1251            case 'd':
     1252            {
     1253                int iValue = va_arg(va, int);
     1254                kSubmitDumpHistoryWrite(pBuf, szTmp, snprintf(szTmp, sizeof(szTmp), "%d", iValue));
     1255                break;
     1256            }
     1257
     1258            case 'u':
     1259            {
     1260                unsigned uValue = va_arg(va, unsigned);
     1261                kSubmitDumpHistoryWrite(pBuf, szTmp, snprintf(szTmp, sizeof(szTmp), "%u", uValue));
     1262                break;
     1263            }
     1264
     1265            case '%':
     1266                kSubmitDumpHistoryWrite(pBuf, "%s", 1);
     1267                break;
     1268
     1269            default:
     1270                assert(0);
     1271        }
     1272    }
     1273    va_end(va);
     1274}
     1275
     1276static void kSubmitDumpHistoryFlush(HISTORYDUMPBUF *pBuf)
     1277{
     1278    if (pBuf->off > 0)
     1279        output_write_text(pBuf->pCtx->pOut, 1, pBuf->pszBuf, pBuf->off);
     1280    pBuf->off = 0;
     1281}
     1282
     1283/**
     1284 * Dumps the history for this worker to stderr in the given context.
     1285 *
     1286 * @param   pCtx                The command execution context. (Typically not a
     1287 *                              real context.)
     1288 * @param   pWorker             The worker instance.
     1289 */
     1290static void kSubmitDumpHistory(PKMKBUILTINCTX pCtx, PWORKERINSTANCE pWorker)
     1291{
     1292    HISTORYDUMPBUF  Buf      = { NULL, 0, 0, pCtx };
     1293    int             iHistory = pWorker->iHistory;
     1294    unsigned        cDumped  = 0;
     1295
     1296    while (cDumped < K_ELEMENTS(pWorker->aHistory) && iHistory > 0)
     1297    {
     1298        unsigned const  idx    = (unsigned)--iHistory % K_ELEMENTS(pWorker->aHistory);
     1299        const char     *pszMsg = (const char *)pWorker->aHistory[idx].pvMsg;
     1300        ssize_t         cbMsg  = pWorker->aHistory[idx].cbMsg;
     1301        const char     *pszExe;
     1302        const char     *pszCwd;
     1303        uint32_t        i;
     1304        uint32_t        cArgs;
     1305        const char     *pszArgs;
     1306        size_t          cbArgs;
     1307        uint32_t        cEnvVars;
     1308        const char     *pszEnvVars;
     1309        size_t          cbEnvVars;
     1310        const char     *pszSpecialEnv;
     1311        char            fNoPchCaching;
     1312        char            fWatcomBrainDamage;
     1313        uint32_t        cPostArgs;
     1314        const char     *pszPostArgs;
     1315        size_t          cbPostArgs;
     1316
     1317        cDumped++;
     1318        if (!pszMsg || !cbMsg)
     1319            break;
     1320
     1321#define SKIP_BYTES(a_cbSkip)    do { pszMsg += (a_cbSkip); cbMsg -= (a_cbSkip); } while (0)
     1322#define SKIP_STR()              do { size_t const cbToSkip = strlen(pszMsg) + 1; SKIP_BYTES(cbToSkip); } while (0)
     1323#define SKIP_STRING_ARRAY(a_cStrings, a_cbPreable) do { \
     1324        for (i = 0; i < (a_cStrings) && cbMsg > 0; i++) { \
     1325            size_t const cbToSkip = (a_cbPreable) + strlen(pszMsg + (a_cbPreable)) + 1; \
     1326            SKIP_BYTES(cbToSkip); \
     1327        } } while (0)
     1328
     1329        /* Decode it: */
     1330        SKIP_BYTES(sizeof(uint32_t) + sizeof("JOB"));
     1331        pszExe = pszMsg;
     1332        SKIP_STR();
     1333        pszCwd = pszMsg;
     1334        SKIP_STR();
     1335
     1336        cArgs  = *(uint32_t *)pszMsg;
     1337        SKIP_BYTES(sizeof(uint32_t));
     1338        pszArgs = pszMsg;
     1339        SKIP_STRING_ARRAY(cArgs, 1 /*fbFlags*/);
     1340        cbArgs = pszMsg - pszArgs;
     1341
     1342        cEnvVars = *(uint32_t *)pszMsg;
     1343        SKIP_BYTES(sizeof(uint32_t));
     1344        pszEnvVars = pszMsg;
     1345        SKIP_STRING_ARRAY(cEnvVars, 0);
     1346        cbEnvVars = pszMsg - pszEnvVars;
     1347
     1348        fWatcomBrainDamage = pszMsg[0] != '\0';
     1349        fNoPchCaching = pszMsg[1] != '\0';
     1350        SKIP_BYTES(2);
     1351
     1352        pszSpecialEnv = pszMsg;
     1353        SKIP_STR();
     1354
     1355        cPostArgs = *(uint32_t *)pszMsg;
     1356        SKIP_BYTES(sizeof(uint32_t));
     1357        pszPostArgs = pszMsg;
     1358        SKIP_STRING_ARRAY(cPostArgs, 0);
     1359        cbPostArgs = pszMsg - pszPostArgs;
     1360
     1361        /* Produce parseable output: */
     1362        kSubmitDumpHistoryPrintf(&Buf, "kWorker %u/%u:\n\tkSubmit", (long)pWorker->pid, iHistory, pszExe);
     1363        if (fNoPchCaching)
     1364            kSubmitDumpHistoryWrite(&Buf, TUPLE(" --no-pch-caching"));
     1365        if (fWatcomBrainDamage)
     1366            kSubmitDumpHistoryWrite(&Buf, TUPLE(" --watcom-brain-damage"));
     1367        if (pszSpecialEnv)
     1368            kSubmitDumpHistoryPrintf(&Buf, " --special-env %s", pszSpecialEnv);
     1369        kSubmitDumpHistoryPrintf(&Buf, " --chdir %s \\\n", pszCwd);
     1370
     1371        pszMsg = pszEnvVars;
     1372        cbMsg  = cbEnvVars;
     1373        for (i = 0; i < cEnvVars && cbMsg > 0; i++)
     1374        {
     1375            kSubmitDumpHistoryPrintf(&Buf, "\t--putenv %s \\\n", pszMsg);
     1376            SKIP_STR();
     1377        }
     1378
     1379        if (cPostArgs > 0)
     1380        {
     1381            kSubmitDumpHistoryWrite(&Buf, TUPLE("\t--post-cmd "));
     1382            pszMsg = pszPostArgs;
     1383            cbMsg  = cbPostArgs;
     1384            for (i = 0; i < cPostArgs && cbMsg > 0; i++)
     1385            {
     1386                kSubmitDumpHistoryPrintf(&Buf, " %s", pszMsg);
     1387                SKIP_STR();
     1388            }
     1389            kSubmitDumpHistoryWrite(&Buf, TUPLE(" \\\n"));
     1390        }
     1391        kSubmitDumpHistoryWrite(&Buf, TUPLE("\t-- \\\n"));
     1392
     1393        pszMsg = pszArgs;
     1394        cbMsg  = cbArgs;
     1395        for (i = 0; i < cArgs && cbMsg > 0; i++)
     1396        {
     1397            SKIP_BYTES(1);
     1398            kSubmitDumpHistoryPrintf(&Buf, i + 1 < cArgs ? "\t%s \\\n" : "\t%s\n", pszMsg);
     1399            SKIP_STR();
     1400        }
     1401
     1402#undef SKIP_BYTES
     1403#undef SKIP_STR
     1404#undef SKIP_STRING_ARRAY
     1405    }
     1406
     1407    kSubmitDumpHistoryFlush(&Buf);
     1408    free(Buf.pszBuf);
     1409}
     1410
     1411
    11101412/**
    11111413 * Marks the worker active.
     
    11681470        if (pWorker->Result.s.bWorkerExiting)
    11691471            kSubmitCloseConnectOnExitingWorker(pCtx, pWorker);
     1472        if (pWorker->Result.s.rcExit && 1)
     1473            kSubmitDumpHistory(pCtx, pWorker);
    11701474        *pPidSpawned = 0;
    11711475        return pWorker->Result.s.rcExit;
     
    12471551        case STATUS_ILLEGAL_INSTRUCTION:        *piSigNo = SIGILL; break;
    12481552    }
     1553    if (pWorker->Result.s.rcExit && 1)
     1554        kSubmitDumpHistory(pCtx, pWorker);
    12491555    if (pWorker->Result.s.bWorkerExiting)
    12501556        kSubmitCloseConnectOnExitingWorker(pCtx, pWorker);
     
    14101716                           "usage: %s [-Z|--zap-env] [-E|--set <var=val>] [-U|--unset <var=val>]\n"
    14111717                           "           [-A|--append <var=val>] [-D|--prepend <var=val>]\n"
    1412                            "           [-C|--chdir <dir>] [--wcc-brain-damage] [--no-pch-caching]\n"
    1413                            "           [-3|--32-bit] [-6|--64-bit] [-v]\n"
     1718                           "           [-s|--special-env <var=val>] [-C|--chdir <dir>]\n"
     1719                           "           [--wcc-brain-damage] [--no-pch-caching]\n"
     1720                           "           [-3|--32-bit] [-6|--64-bit] [-v] [--debug-dump-history]\n"
    14141721                           "           [-P|--post-cmd <cmd> [args]] -- <program> [args]\n"
    14151722                           "   or: %s --help\n"
     
    14201727                           "    Zaps the environment. Position dependent.\n"
    14211728                           "  -E, --set <var>=[value]\n"
    1422                            "    Sets an enviornment variable putenv fashion. Position dependent.\n"
     1729                           "    Sets an environment variable putenv fashion. Position dependent.\n"
    14231730                           "  -U, --unset <var>\n"
    14241731                           "    Removes an environment variable. Position dependent.\n"
     
    14271734                           "  -D,--prepend <var>=<value>\n"
    14281735                           "    Prepends the given value to the environment variable.\n"
     1736                           "  -s,--special-env <var>=<value>\n"
     1737                           "    Same as --set, but flags the variable for further expansion\n"
     1738                           "    within kWorker. Replacements:\n"
     1739                           "      @@PROCESSOR_GROUP@@   - The processor group number.\n"
     1740                           "      @@AUTHENTICATION_ID@@ - The authentication ID from the process token.\n"
     1741                           "      @@PID@@               - The kWorker process ID.\n"
     1742                           "      @@@@                  - Escaped \"@@\".\n"
     1743                           "      @@DEBUG_COUNTER@@     - An ever increasing counter (starts at zero).\n"
    14291744                           "  -C, --chdir <dir>\n"
    14301745                           "    Specifies the current directory for the program.  Relative paths\n"
     
    14411756                           "  -v,--verbose\n"
    14421757                           "    More verbose execution.\n"
     1758                           "  --debug-dump-history\n"
     1759                           "    Dump the history as of the submitted command.  Handy for debuging\n"
     1760                           "    trouble caused by a previous job.\n"
    14431761                           "  -P|--post-cmd <cmd> ...\n"
    14441762                           "    For running a built-in command on the output, specifying the command\n"
     
    14581776int kmk_builtin_kSubmit(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx, struct child *pChild, pid_t *pPidSpawned)
    14591777{
     1778#ifdef KBUILD_OS_WINDOWS
     1779    static int      s_fInitialized      = 0;
     1780#endif
    14601781    int             rcExit = 0;
    14611782    int             iArg;
     
    14641785    char          **papszEnvVars;
    14651786    const char     *pszExecutable       = NULL;
     1787    const char     *pszSpecialEnv       = NULL;
    14661788    int             iPostCmd            = argc;
    14671789    int             cPostCmdArgs        = 0;
     
    14691791    int             fWatcomBrainDamage  = 0;
    14701792    int             fNoPchCaching       = 0;
     1793    int             fDebugDumpHistory   = 0;
    14711794    int             cVerbosity          = 0;
    14721795    size_t const    cbCwdBuf            = GET_PATH_MAX;
    14731796    PATH_VAR(szCwd);
     1797
     1798#ifdef KBUILD_OS_WINDOWS
     1799    /*
     1800     * First time thru we must perform some initializations.
     1801     */
     1802    if (s_fInitialized)
     1803    { }
     1804    else
     1805    {
     1806        MkWinChildInitCpuGroupAllocator(&g_SubmitProcessorGroupAllocator);
     1807# if K_ARCH_BITS == 64
     1808        MkWinChildInitCpuGroupAllocator(&g_SubmitProcessorGroupAllocator32);
     1809# endif
     1810        *(FARPROC *)&g_pfnSetThreadGroupAffinity = GetProcAddress(GetModuleHandleW(L"KERNEL32.DLL"), "SetThreadGroupAffinity");
     1811        s_fInitialized = 1;
     1812    }
     1813#endif
    14741814
    14751815    /*
     
    15331873                }
    15341874
     1875                if (strcmp(pszArg, "debug-dump-history") == 0)
     1876                {
     1877                    fDebugDumpHistory = 1;
     1878                    continue;
     1879                }
     1880
     1881
    15351882                /* convert to short. */
    15361883                if (strcmp(pszArg, "help") == 0)
     
    15511898                else if (strcmp(pszArg, "chdir") == 0)
    15521899                    chOpt = 'C';
     1900                else if (strcmp(pszArg, "set-special") == 0)
     1901                    chOpt = 's';
    15531902                else if (strcmp(pszArg, "post-cmd") == 0)
    15541903                    chOpt = 'P';
     
    15811930                    case 'D':
    15821931                    case 'e':
     1932                    case 's':
    15831933                        if (*pszArg != '\0')
    15841934                            pszValue = pszArg + (*pszArg == ':' || *pszArg == '=');
     
    16281978                    case 'C':
    16291979                        rcExit = kBuiltinOptChDir(pCtx, szCwd, cbCwdBuf, pszValue);
     1980                        if (rcExit == 0)
     1981                            break;
     1982                        return rcExit;
     1983
     1984                    case 's':
     1985                        if (pszSpecialEnv)
     1986                            return errx(pCtx, 1, "The -s option can only be used once!");
     1987                        pszSpecialEnv = pszValue;
     1988                        rcExit = kBuiltinOptEnvSet(pCtx, &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);
    16301989                        if (rcExit == 0)
    16311990                            break;
     
    16872046        uint32_t        cbMsg;
    16882047        void           *pvMsg   = kSubmitComposeJobMessage(pszExecutable, &argv[iArg], papszEnvVars, szCwd,
    1689                                                            fWatcomBrainDamage, fNoPchCaching,
     2048                                                           fWatcomBrainDamage, fNoPchCaching, pszSpecialEnv,
    16902049                                                           &argv[iPostCmd], cPostCmdArgs, &cbMsg);
    16912050        PWORKERINSTANCE pWorker = kSubmitSelectWorkSpawnNewIfNecessary(pCtx, cBitsWorker, cVerbosity);
     
    17032062            rcExit = kSubmitSendJobMessage(pCtx, pWorker, pvMsg, cbMsg, 0 /*fNoRespawning*/, cVerbosity);
    17042063            if (rcExit == 0)
     2064            {
     2065                pvMsg = kSubmitUpdateHistory(pWorker, pvMsg, cbMsg);
     2066                if (fDebugDumpHistory)
     2067                    kSubmitDumpHistory(pCtx, pWorker);
    17052068                rcExit = kSubmitMarkActive(pCtx, pWorker, cVerbosity, pChild, pPidSpawned);
     2069            }
    17062070
    17072071            if (!g_fAtExitRegistered)
     
    17232087}
    17242088
    1725 
    1726 
Note: See TracChangeset for help on using the changeset viewer.