Changeset 3199 in kBuild
- Timestamp:
- Mar 28, 2018 6:56:21 PM (7 years ago)
- Location:
- trunk/src
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kWorker/kWorker.c
r3198 r3199 928 928 929 929 /** Whether control-C/SIGINT or Control-Break/SIGBREAK have been seen. */ 930 static KBOOL volatile g_fCtrlC = K_FALSE; 930 static 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 934 static HANDLE g_hPipe = INVALID_HANDLE_VALUE; 935 #else 936 static int g_hPipe = -1; 937 #endif 938 931 939 932 940 /* Further down. */ … … 6657 6665 KUPTR const idxHandle = KW_HANDLE_TO_INDEX(hFile); 6658 6666 g_cWriteFileCalls++; 6659 kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread || g_ fCtrlC);6667 kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread || g_rcCtrlC != 0); 6660 6668 if (idxHandle < g_Sandbox.cHandles) 6661 6669 { … … 7368 7376 BOOL fRet; 7369 7377 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); 7371 7379 if (idxHandle < g_Sandbox.cHandles) 7372 7380 { … … 9526 9534 KU32 const g_cSandboxGetProcReplacements = K_ELEMENTS(g_aSandboxGetProcReplacements); 9527 9535 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 */ 9542 static 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 9528 9554 9529 9555 /** … … 9535 9561 static BOOL WINAPI kwSandboxCtrlHandler(DWORD dwCtrlType) 9536 9562 { 9563 DWORD cbIgn; 9564 int volatile rc; /* volatile for debugging */ 9565 int volatile rcPrev; 9566 const char *pszMsg; 9537 9567 switch (dwCtrlType) 9538 9568 { 9539 9569 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"; 9543 9572 break; 9544 9573 9545 9574 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"; 9549 9577 break; 9550 9578 9551 9579 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"; 9555 9582 break; 9556 9583 9557 9584 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"; 9561 9587 break; 9562 9588 9563 9589 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"; 9567 9592 break; 9568 9593 9569 9594 default: 9570 9595 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); 9573 9622 return TRUE; 9574 9623 } … … 10607 10656 KU8 const *pbBuf = (KU8 const *)pvBuf; 10608 10657 KU32 cbLeft = cbToWrite; 10609 for (;;)10658 while (g_rcCtrlC == 0) 10610 10659 { 10611 10660 DWORD cbActuallyWritten = 0; … … 10627 10676 } 10628 10677 } 10678 return -1; 10629 10679 } 10630 10680 … … 10646 10696 KU8 *pbBuf = (KU8 *)pvBuf; 10647 10697 KU32 cbLeft = cbToRead; 10648 for (;;)10698 while (g_rcCtrlC == 0) 10649 10699 { 10650 10700 DWORD cbActuallyRead = 0; … … 10671 10721 } 10672 10722 } 10723 return -1; 10673 10724 } 10674 10725 … … 11238 11289 { 11239 11290 close(fdNul); 11240 kHlpAssert(GetStdHandle(STD_INPUT_HANDLE) != hPipe);11241 11291 hPipe = hDuplicate; 11242 11292 } … … 11257 11307 return kwErrPrintfRc(2, "The specified --pipe %p is not a pipe handle: type %#x (last err %u)!\n", 11258 11308 GetFileType(hPipe), GetLastError()); 11309 g_hPipe = hPipe; 11259 11310 11260 11311 /* … … 11296 11347 /* The first string after the header is the command. */ 11297 11348 psz = (const char *)&pbMsgBuf[sizeof(cbMsg)]; 11298 if (strcmp(psz, "JOB") == 0) 11349 if ( strcmp(psz, "JOB") == 0 11350 && g_rcCtrlC == 0) 11299 11351 { 11300 11352 struct … … 11314 11366 { 11315 11367 kwSandboxCleanupLate(&g_Sandbox); 11316 continue; 11368 if (g_rcCtrlC == 0) 11369 continue; 11317 11370 } 11318 11371 } … … 11347 11400 if (getenv("KWORKER_STATS") != NULL) 11348 11401 kwPrintStats(); 11349 return rc > 0 ? 0 : 1;11402 return g_rcCtrlC != 0 ? g_rcCtrlC : rc > 0 ? 0 : 1; 11350 11403 } 11351 11404 } -
trunk/src/kmk/kmkbuiltin/kSubmit.c
r3198 r3199 110 110 /** For overlapped read (have valid event semaphore). */ 111 111 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 112 118 #else 113 119 /** The socket descriptor we use to talk to the kWorker process. */ … … 424 430 wchar_t wszPipeName[128]; 425 431 HANDLE hWorkerPipe; 426 SECURITY_ATTRIBUTES SecAttrs = { /*nLength:*/ sizeof(SecAttrs), /*pAttrs:*/ NULL, /*bInheritHandle:*/ TRUE };427 432 int iProcessorGroup = -1; /** @todo determine process group. */ 428 433 429 434 /* 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. 431 436 */ 432 437 if (s_fDenyRemoteClients == ~(DWORD)0) … … 441 446 65536 /*cbInBuffer*/, 442 447 0 /*cMsDefaultTimeout -> 50ms*/, 443 &SecAttrs /*inherit */);448 NULL /* pSecAttr - no inherit */); 444 449 if (hWorkerPipe != INVALID_HANDLE_VALUE) 445 450 { … … 519 524 BOOL afReplace[3] = { TRUE, FALSE, FALSE }; 520 525 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 521 534 rc = nt_child_inject_standard_handles(ProcInfo.hProcess, afReplace, ahReplace, szErrMsg, sizeof(szErrMsg)); 522 535 if (rc == 0) … … 570 583 } 571 584 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)", 573 586 GetLastError(), wszExecutable, wszCommandLine); 574 587 CloseHandle(pWorker->OverlappedRead.hEvent); … … 638 651 pWorker->OverlappedRead.hEvent = INVALID_HANDLE_VALUE; 639 652 653 if (pWorker->pStdOut) 654 MkWinChildcareWorkerDrainPipes(NULL, pWorker->pStdOut, pWorker->pStdErr); 655 640 656 /* It's probably shutdown already, if not give it 10 milliseconds before 641 657 we terminate it forcefully. */ … … 644 660 { 645 661 BOOL fRc = TerminateProcess(pWorker->hProcess, 127); 662 663 if (pWorker->pStdOut) 664 MkWinChildcareWorkerDrainPipes(NULL, pWorker->pStdOut, pWorker->pStdErr); 665 646 666 rcWait = WaitForSingleObject(pWorker->hProcess, 100); 647 667 if (rcWait != WAIT_OBJECT_0) 648 668 warnx(pCtx, "WaitForSingleObject returns %u (and TerminateProcess %d)", rcWait, fRc); 649 669 } 670 671 if (pWorker->pStdOut) 672 MkWinChildcareWorkerDrainPipes(NULL, pWorker->pStdOut, pWorker->pStdErr); 650 673 651 674 if (!CloseHandle(pWorker->hProcess)) … … 719 742 pWorker = (PWORKERINSTANCE)xcalloc(sizeof(*pWorker)); 720 743 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 733 774 734 775 free(pWorker); … … 1109 1150 } 1110 1151 # 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) 1112 1154 { /* likely */ } 1113 1155 else -
trunk/src/kmk/w32/winchildren.c
r3197 r3199 87 87 * Header Files * 88 88 *********************************************************************************************************************************/ 89 #include <Windows.h> 90 #include <Winternl.h> 91 89 92 #include "../makeint.h" 90 93 #include "../job.h" … … 94 97 #include "winchildren.h" 95 98 96 #include <Windows.h>97 #include <Winternl.h>98 99 #include <assert.h> 99 100 #include <process.h> … … 132 133 /** Pointer to a windows child process. */ 133 134 typedef struct WINCHILD *PWINCHILD; 135 134 136 135 137 /** … … 250 252 /** Parameter for the cleanup callback. */ 251 253 void *pvSubmitWorker; 254 /** Standard output catching pipe. Optional. */ 255 PWINCCWPIPE pStdOut; 256 /** Standard error catching pipe. Optional. */ 257 PWINCCWPIPE pStdErr; 252 258 } Submit; 253 259 … … 263 269 /** WINCHILD::uMagic value. */ 264 270 #define WINCHILD_MAGIC 0xbabebabeU 265 266 /**267 * A childcare worker pipe.268 */269 typedef struct WINCCWPIPE270 {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 before282 * we start catching output from a new child and use in the CL.exe283 * supression heuristics. */284 BOOL fHaveWrittenOut;285 /** Number of bytes at the start of the buffer that we've already286 * 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;298 271 299 272 … … 330 303 HANDLE hEvtIdle; 331 304 /** The pipe catching standard output from a child. */ 332 WINCCWPIPEStdOut;305 PWINCCWPIPE pStdOut; 333 306 /** The pipe catching standard error from a child. */ 334 WINCCWPIPEStdErr;307 PWINCCWPIPE pStdErr; 335 308 336 309 /** Pointer to the current child. */ … … 744 717 { 745 718 #ifdef CONFIG_WITH_OUTPUT_IN_MEMORY 746 if (pChild ->pMkChild)719 if (pChild && pChild->pMkChild) 747 720 { 748 721 output_write_bin(&pChild->pMkChild->output, pPipe->iWhich == 2, &pPipe->pbBuffer[pPipe->cbWritten], cbUnwritten); … … 799 772 * reshuffle the buffer if desirable. 800 773 * 801 * @param pChild The child. 774 * @param pChild The child. Optional (kSubmit). 802 775 * @param iWhich Which standard descriptor number. 803 776 * @param cbNewData How much more output was caught. … … 838 811 /* If this is a potential CL.EXE process, we will keep the source 839 812 filename unflushed and maybe discard it at the end. */ 840 else if ( pChild->fProbableClExe 813 else if ( pChild 814 && pChild->fProbableClExe 841 815 && pPipe->iWhich == 1 842 816 && offRest == pPipe->offPendingRead … … 849 823 DWORD cbToWrite = offRest - offStart; 850 824 #ifdef CONFIG_WITH_OUTPUT_IN_MEMORY 851 if (pChild ->pMkChild)825 if (pChild && pChild->pMkChild) 852 826 { 853 827 output_write_bin(&pChild->pMkChild->output, pPipe->iWhich == 2, &pPipe->pbBuffer[offStart], cbToWrite); … … 884 858 * Catches output from the given pipe. 885 859 * 886 * @param pChild The child. 860 * @param pChild The child. Optional (kSubmit). 887 861 * @param pPipe The pipe. 888 862 * @param fDraining Set if we're draining the pipe after the process … … 906 880 else 907 881 { 908 MkWinChildError(pChild ->pWorker, 2, "GetOverlappedResult failed: %u\n", GetLastError());882 MkWinChildError(pChild ? pChild->pWorker : NULL, 2, "GetOverlappedResult failed: %u\n", GetLastError()); 909 883 pPipe->fReadPending = FALSE; 910 884 if (fDraining) … … 934 908 pPipe->fReadPending = TRUE; 935 909 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", 937 912 pPipe->iWhich == 1 ? "output" : "error", GetLastError()); 938 913 return; … … 946 921 * Makes sure the output pipes are drained and pushed to output. 947 922 * 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 */ 927 void MkWinChildcareWorkerDrainPipes(PWINCHILD pChild, PWINCCWPIPE pStdOut, PWINCCWPIPE pStdErr) 928 { 929 mkWinChildcareWorkerCatchOutput(pChild, pStdOut, TRUE /*fDraining*/); 930 mkWinChildcareWorkerCatchOutput(pChild, pStdErr, TRUE /*fDraining*/); 955 931 956 932 /* 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; 966 943 else 967 p Worker->StdOut.cbWritten = pWorker->StdOut.offPendingRead;944 pStdOut->cbWritten = pStdOut->offPendingRead; 968 945 } 969 946 else 970 947 { 971 mkWinChildcareWorkerFlushUnwritten(pChild, &pWorker->StdOut);972 mkWinChildcareWorkerFlushUnwritten(pChild, &pWorker->StdErr);948 mkWinChildcareWorkerFlushUnwritten(pChild, pStdOut); 949 mkWinChildcareWorkerFlushUnwritten(pChild, pStdErr); 973 950 } 974 951 } … … 992 969 993 970 /* 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; 996 973 997 974 for (;;) … … 1005 982 else 1006 983 { 1007 HANDLE ahHandles[3] = { hProcess, pWorker-> StdOut.hEvent, pWorker->StdErr.hEvent };984 HANDLE ahHandles[3] = { hProcess, pWorker->pStdOut->hEvent, pWorker->pStdErr->hEvent }; 1008 985 dwStatus = WaitForMultipleObjects(3, ahHandles, FALSE /*fWaitAll*/, 1000 /*ms*/); 1009 986 if (dwStatus == WAIT_OBJECT_0 + 1) 1010 mkWinChildcareWorkerCatchOutput(pChild, &pWorker->StdOut, FALSE /*fDraining*/);987 mkWinChildcareWorkerCatchOutput(pChild, pWorker->pStdOut, FALSE /*fDraining*/); 1011 988 else if (dwStatus == WAIT_OBJECT_0 + 2) 1012 mkWinChildcareWorkerCatchOutput(pChild, &pWorker->StdErr, FALSE /*fDraining*/);989 mkWinChildcareWorkerCatchOutput(pChild, pWorker->pStdErr, FALSE /*fDraining*/); 1013 990 } 1014 991 assert(dwStatus != WAIT_FAILED); … … 1024 1001 pChild->iExitCode = (int)dwExitCode; 1025 1002 if (fCatchOutput) 1026 mkWinChildcareWorkerDrainPipes(pWorker, pChild);1003 MkWinChildcareWorkerDrainPipes(pChild, pWorker->pStdOut, pWorker->pStdErr); 1027 1004 return dwExitCode; 1028 1005 } … … 1205 1182 { 1206 1183 pafReplace[1] = TRUE; 1207 pahChild[1] = pWorker-> StdOut.hPipeChild;1184 pahChild[1] = pWorker->pStdOut->hPipeChild; 1208 1185 } 1209 1186 if (!pafReplace[2]) 1210 1187 { 1211 1188 pafReplace[2] = TRUE; 1212 pahChild[2] = pWorker-> StdErr.hPipeChild;1189 pahChild[2] = pWorker->pStdErr->hPipeChild; 1213 1190 } 1214 1191 } … … 2309 2286 static void mkWinChildcareWorkerThreadHandleSubmit(PWINCHILDCAREWORKER pWorker, PWINCHILD pChild) 2310 2287 { 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 */ 2312 2307 for (;;) 2313 2308 { 2314 2309 int iExitCode = -42; 2315 2310 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 } 2319 2323 if (kSubmitSubProcGetResult((intptr_t)pvSubmitWorker, &iExitCode, &iSignal) == 0) 2320 2324 { 2325 if (pChild->u.Submit.pStdOut) 2326 MkWinChildcareWorkerDrainPipes(pChild, pChild->u.Submit.pStdOut, pChild->u.Submit.pStdErr); 2327 2321 2328 pChild->iExitCode = iExitCode; 2322 2329 pChild->iSignal = iSignal; … … 2485 2492 * our end of the pipe. Silly that they don't offer an API that does this. 2486 2493 * 2487 * @returns Success indicator.2494 * @returns The pipe that was created. NULL on failure. 2488 2495 * @param pPipe The structure for the pipe. 2489 2496 * @param iWhich Which standard descriptor this is a pipe for. 2490 2497 * @param idxWorker The worker index. 2491 2498 */ 2492 static BOOL mkWinChildcareCreateWorkerPipe(PWINCCWPIPE pPipe,unsigned iWhich, unsigned int idxWorker)2499 PWINCCWPIPE MkWinChildcareCreateWorkerPipe(unsigned iWhich, unsigned int idxWorker) 2493 2500 { 2494 2501 /* … … 2534 2541 if (hEvent != NULL) 2535 2542 { 2543 PWINCCWPIPE pPipe = (PWINCCWPIPE)xcalloc(sizeof(*pPipe)); 2536 2544 pPipe->hPipeMine = hPipeRead; 2537 2545 pPipe->hPipeChild = hPipeWrite; … … 2541 2549 pPipe->cbBuffer = cbPipe; 2542 2550 pPipe->pbBuffer = xcalloc(cbPipe); 2543 return TRUE;2551 return pPipe; 2544 2552 } 2545 2553 2546 2554 CloseHandle(hPipeWrite); 2547 2555 CloseHandle(hPipeRead); 2548 return FALSE;2556 return NULL; 2549 2557 } 2550 2558 CloseHandle(hPipeRead); 2551 2559 } 2552 2560 } 2553 return FALSE;2561 return NULL; 2554 2562 } 2555 2563 … … 2559 2567 * @param pPipe The pipe. 2560 2568 */ 2561 static void mkWinChildcareDeleteWorkerPipe(PWINCCWPIPE pPipe)2569 void MkWinChildcareDeleteWorkerPipe(PWINCCWPIPE pPipe) 2562 2570 { 2563 2571 if (pPipe->hPipeChild != NULL) … … 2602 2610 if (pWorker->hEvtIdle) 2603 2611 { 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) 2607 2617 { 2608 2618 /* Before we start the thread, assign it to a processor group. */ … … 2645 2655 /* Bail out! */ 2646 2656 ONS (error, NILF, "_beginthreadex failed: %u (%s)\n", errno, strerror(errno)); 2647 mkWinChildcareDeleteWorkerPipe(&pWorker->StdErr);2657 MkWinChildcareDeleteWorkerPipe(pWorker->pStdErr); 2648 2658 } 2649 2659 else 2650 2660 ON (error, NILF, "Failed to create stderr pipe: %u\n", GetLastError()); 2651 mkWinChildcareDeleteWorkerPipe(&pWorker->StdOut);2661 MkWinChildcareDeleteWorkerPipe(pWorker->pStdOut); 2652 2662 } 2653 2663 else … … 2981 2991 if (CreatePipe(&hReadPipe, &hWritePipe, NULL, 0 /* default size */)) 2982 2992 { 2983 if (SetHandleInformation(hWritePipe, HANDLE_FLAG_INHERIT /* clear */ , HANDLE_FLAG_INHERIT /*set*/))2993 //if (SetHandleInformation(hWritePipe, HANDLE_FLAG_INHERIT /* clear */ , HANDLE_FLAG_INHERIT /*set*/)) 2984 2994 { 2985 2995 int fdReadPipe = _open_osfhandle((intptr_t)hReadPipe, O_RDONLY); … … 3033 3043 ON(error, NILF, _("_open_osfhandle failed on pipe: %u\n"), errno); 3034 3044 } 3035 else3036 ON(error, NILF, _("SetHandleInformation failed on pipe: %u\n"), GetLastError());3045 //else 3046 // ON(error, NILF, _("SetHandleInformation failed on pipe: %u\n"), GetLastError()); 3037 3047 if (hReadPipe != INVALID_HANDLE_VALUE) 3038 3048 CloseHandle(hReadPipe); … … 3109 3119 * @param pvSubmitWorker The argument to pass back to kSubmit to clean up. 3110 3120 * @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 */ 3124 int MkWinChildCreateSubmit(intptr_t hEvent, void *pvSubmitWorker, PWINCCWPIPE pStdOut, PWINCCWPIPE pStdErr, pid_t *pPid) 3113 3125 { 3114 3126 PWINCHILD pChild = mkWinChildNew(WINCHILDTYPE_SUBMIT); 3115 3127 pChild->u.Submit.hEvent = (HANDLE)hEvent; 3116 3128 pChild->u.Submit.pvSubmitWorker = pvSubmitWorker; 3129 pChild->u.Submit.pStdOut = pStdOut; 3130 pChild->u.Submit.pStdErr = pStdErr; 3117 3131 return mkWinChildPushToCareWorker(pChild, pPid); 3118 3132 } -
trunk/src/kmk/w32/winchildren.h
r3195 r3199 27 27 #define INCLUDED_WINCHILDREN_H 28 28 29 #ifdef DECLARE_HANDLE 30 /** 31 * A childcare worker pipe. 32 */ 33 typedef 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 63 typedef struct WINCCWPIPE *PWINCCWPIPE; 29 64 30 65 void MkWinChildInit(unsigned int cJobSlot); … … 39 74 int MkWinChildCreateAppend(const char *pszFilename, char **ppszAppend, size_t cbAppend, int fTruncate, 40 75 struct child *pMkChild, pid_t *pPid); 41 int MkWinChildCreateSubmit(intptr_t hEvent, void *pvSubmitWorker, pid_t *pPid); 76 77 int MkWinChildCreateSubmit(intptr_t hEvent, void *pvSubmitWorker, PWINCCWPIPE pStdOut, PWINCCWPIPE pStdErr, pid_t *pPid); 78 PWINCCWPIPE MkWinChildcareCreateWorkerPipe(unsigned iWhich, unsigned int idxWorker); 79 void MkWinChildcareWorkerDrainPipes(struct WINCHILD *pChild, PWINCCWPIPE pStdOut, PWINCCWPIPE pStdErr); 80 void MkWinChildcareDeleteWorkerPipe(PWINCCWPIPE pPipe); 81 42 82 int MkWinChildCreateRedirect(intptr_t hProcess, pid_t *pPid); 43 83 # ifdef DECLARE_HANDLE … … 55 95 int MkWinChildUnrelatedCloseOnExec(int fd); 56 96 97 57 98 #endif 58 99 -
trunk/src/lib/nt/kFsCache.h
r3184 r3199 494 494 * Generic logging. 495 495 * @param a Argument list for kFsCacheDbgPrintf */ 496 #if def NDEBUG496 #if 1 /*def NDEBUG - enable when needed! */ 497 497 # define KFSCACHE_LOG(a) do { } while (0) 498 498 #else
Note:
See TracChangeset
for help on using the changeset viewer.