Changeset 3313 for trunk/src/kmk/kmkbuiltin/kSubmit.c
- Timestamp:
- Mar 16, 2020, 3:31:38 AM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kmk/kmkbuiltin/kSubmit.c
r3224 r3313 121 121 int fdSocket; 122 122 #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]; 123 134 124 135 /** What it's busy with. NULL if idle. */ … … 181 192 182 193 #ifdef KBUILD_OS_WINDOWS 194 /** The processor group allocator state. */ 195 static MKWINCHILDCPUGROUPALLOCSTATE g_SubmitProcessorGroupAllocator; 196 # if K_ARCH_BITS == 64 197 /** The processor group allocator state for 32-bit processes. */ 198 static MKWINCHILDCPUGROUPALLOCSTATE g_SubmitProcessorGroupAllocator32; 199 # endif 200 #endif 201 202 #ifdef KBUILD_OS_WINDOWS 183 203 /** Pointer to kernel32!SetThreadGroupAffinity. */ 184 204 static BOOL (WINAPI *g_pfnSetThreadGroupAffinity)(HANDLE, const GROUP_AFFINITY*, GROUP_AFFINITY *); … … 428 448 { 429 449 #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 434 464 435 465 /* … … 464 494 { 465 495 extern int process_priority; /* main.c */ 466 wchar_t wszCommandLine[MAX_PATH * 3 ];496 wchar_t wszCommandLine[MAX_PATH * 3 + 32]; 467 497 wchar_t *pwszDst = wszCommandLine; 468 498 size_t cwcDst = K_ELEMENTS(wszCommandLine); … … 490 520 cwcDst -= cwc; 491 521 } 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 } 492 529 *pwszDst = '\0'; 493 530 … … 549 586 warnx(pCtx, "warning: failed to set kWorker thread priority: %u\n", GetLastError()); 550 587 551 if (iProcessorGroup >= 0 )588 if (iProcessorGroup >= 0 && g_pfnSetThreadGroupAffinity) 552 589 { 553 590 GROUP_AFFINITY NewAff = { ~(uintptr_t)0, (WORD)iProcessorGroup, 0, 0, 0 }; … … 789 826 * @param fWatcomBrainDamage The wcc/wcc386 workaround. 790 827 * @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. 791 830 * @param papszPostCmdArgs The post command and it's arguments. 792 831 * @param cPostCmdArgs Number of post command argument, including the … … 795 834 */ 796 835 static 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, 798 837 char **papszPostCmdArgs, uint32_t cPostCmdArgs, uint32_t *pcbMsg) 799 838 { 800 839 size_t cbTmp; 840 size_t cbSpecialEnv; 801 841 uint32_t i; 802 842 uint32_t cbMsg; … … 833 873 cbMsg += 1; /* fNoPchCaching */ 834 874 875 cbSpecialEnv = pszSpecialEnv ? strchr(pszSpecialEnv, '=') - pszSpecialEnv : 0; 876 cbMsg += cbSpecialEnv + 1; 877 835 878 cbMsg += sizeof(cPostCmdArgs); 836 879 for (i = 0; i < cPostCmdArgs; i++) … … 858 901 pbCursor += cbTmp; 859 902 860 /* argument */903 /* arguments */ 861 904 memcpy(pbCursor, &cArgs, sizeof(cArgs)); 862 905 pbCursor += sizeof(cArgs); … … 884 927 *pbCursor++ = fWatcomBrainDamage != 0; 885 928 *pbCursor++ = fNoPchCaching != 0; 929 930 /* Special environment variable name. */ 931 memcpy(pbCursor, pszSpecialEnv, cbSpecialEnv); 932 pbCursor += cbSpecialEnv; 933 *pbCursor++ = '\0'; 886 934 887 935 /* post command */ … … 1108 1156 #endif /* KBUILD_OS_WINDOWS */ 1109 1157 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 */ 1167 static 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 1178 typedef struct HISTORYDUMPBUF 1179 { 1180 char *pszBuf; 1181 size_t cbBuf; 1182 size_t off; 1183 PKMKBUILTINCTX pCtx; 1184 } HISTORYDUMPBUF; 1185 1186 1187 static 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 1203 static 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 1276 static 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 */ 1290 static 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 1110 1412 /** 1111 1413 * Marks the worker active. … … 1168 1470 if (pWorker->Result.s.bWorkerExiting) 1169 1471 kSubmitCloseConnectOnExitingWorker(pCtx, pWorker); 1472 if (pWorker->Result.s.rcExit && 1) 1473 kSubmitDumpHistory(pCtx, pWorker); 1170 1474 *pPidSpawned = 0; 1171 1475 return pWorker->Result.s.rcExit; … … 1247 1551 case STATUS_ILLEGAL_INSTRUCTION: *piSigNo = SIGILL; break; 1248 1552 } 1553 if (pWorker->Result.s.rcExit && 1) 1554 kSubmitDumpHistory(pCtx, pWorker); 1249 1555 if (pWorker->Result.s.bWorkerExiting) 1250 1556 kSubmitCloseConnectOnExitingWorker(pCtx, pWorker); … … 1410 1716 "usage: %s [-Z|--zap-env] [-E|--set <var=val>] [-U|--unset <var=val>]\n" 1411 1717 " [-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" 1414 1721 " [-P|--post-cmd <cmd> [args]] -- <program> [args]\n" 1415 1722 " or: %s --help\n" … … 1420 1727 " Zaps the environment. Position dependent.\n" 1421 1728 " -E, --set <var>=[value]\n" 1422 " Sets an envi ornment variable putenv fashion. Position dependent.\n"1729 " Sets an environment variable putenv fashion. Position dependent.\n" 1423 1730 " -U, --unset <var>\n" 1424 1731 " Removes an environment variable. Position dependent.\n" … … 1427 1734 " -D,--prepend <var>=<value>\n" 1428 1735 " 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" 1429 1744 " -C, --chdir <dir>\n" 1430 1745 " Specifies the current directory for the program. Relative paths\n" … … 1441 1756 " -v,--verbose\n" 1442 1757 " 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" 1443 1761 " -P|--post-cmd <cmd> ...\n" 1444 1762 " For running a built-in command on the output, specifying the command\n" … … 1458 1776 int kmk_builtin_kSubmit(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx, struct child *pChild, pid_t *pPidSpawned) 1459 1777 { 1778 #ifdef KBUILD_OS_WINDOWS 1779 static int s_fInitialized = 0; 1780 #endif 1460 1781 int rcExit = 0; 1461 1782 int iArg; … … 1464 1785 char **papszEnvVars; 1465 1786 const char *pszExecutable = NULL; 1787 const char *pszSpecialEnv = NULL; 1466 1788 int iPostCmd = argc; 1467 1789 int cPostCmdArgs = 0; … … 1469 1791 int fWatcomBrainDamage = 0; 1470 1792 int fNoPchCaching = 0; 1793 int fDebugDumpHistory = 0; 1471 1794 int cVerbosity = 0; 1472 1795 size_t const cbCwdBuf = GET_PATH_MAX; 1473 1796 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 1474 1814 1475 1815 /* … … 1533 1873 } 1534 1874 1875 if (strcmp(pszArg, "debug-dump-history") == 0) 1876 { 1877 fDebugDumpHistory = 1; 1878 continue; 1879 } 1880 1881 1535 1882 /* convert to short. */ 1536 1883 if (strcmp(pszArg, "help") == 0) … … 1551 1898 else if (strcmp(pszArg, "chdir") == 0) 1552 1899 chOpt = 'C'; 1900 else if (strcmp(pszArg, "set-special") == 0) 1901 chOpt = 's'; 1553 1902 else if (strcmp(pszArg, "post-cmd") == 0) 1554 1903 chOpt = 'P'; … … 1581 1930 case 'D': 1582 1931 case 'e': 1932 case 's': 1583 1933 if (*pszArg != '\0') 1584 1934 pszValue = pszArg + (*pszArg == ':' || *pszArg == '='); … … 1628 1978 case 'C': 1629 1979 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); 1630 1989 if (rcExit == 0) 1631 1990 break; … … 1687 2046 uint32_t cbMsg; 1688 2047 void *pvMsg = kSubmitComposeJobMessage(pszExecutable, &argv[iArg], papszEnvVars, szCwd, 1689 fWatcomBrainDamage, fNoPchCaching, 2048 fWatcomBrainDamage, fNoPchCaching, pszSpecialEnv, 1690 2049 &argv[iPostCmd], cPostCmdArgs, &cbMsg); 1691 2050 PWORKERINSTANCE pWorker = kSubmitSelectWorkSpawnNewIfNecessary(pCtx, cBitsWorker, cVerbosity); … … 1703 2062 rcExit = kSubmitSendJobMessage(pCtx, pWorker, pvMsg, cbMsg, 0 /*fNoRespawning*/, cVerbosity); 1704 2063 if (rcExit == 0) 2064 { 2065 pvMsg = kSubmitUpdateHistory(pWorker, pvMsg, cbMsg); 2066 if (fDebugDumpHistory) 2067 kSubmitDumpHistory(pCtx, pWorker); 1705 2068 rcExit = kSubmitMarkActive(pCtx, pWorker, cVerbosity, pChild, pPidSpawned); 2069 } 1706 2070 1707 2071 if (!g_fAtExitRegistered) … … 1723 2087 } 1724 2088 1725 1726
Note:
See TracChangeset
for help on using the changeset viewer.