| 1326 | } |
| 1327 | |
| 1328 | int kwsysProcess_WaitForExit(kwsysProcess* cp, double* userTimeout) |
| 1329 | { |
| 1330 | int i; |
| 1331 | int pipe; |
| 1332 | |
| 1333 | /* Make sure we are executing a process. */ |
| 1334 | if (!cp || cp->State != kwsysProcess_State_Executing) { |
| 1335 | return 1; |
| 1336 | } |
| 1337 | |
| 1338 | /* Wait for the process to terminate. Ignore all data. */ |
| 1339 | while ((pipe = kwsysProcess_WaitForData(cp, 0, 0, userTimeout)) > 0) { |
| 1340 | if (pipe == kwsysProcess_Pipe_Timeout) { |
| 1341 | /* The user timeout has expired. */ |
| 1342 | return 0; |
| 1343 | } |
| 1344 | } |
| 1345 | |
| 1346 | KWSYSPE_DEBUG((stderr, "no more data\n")); |
| 1347 | |
| 1348 | /* When the last pipe closes in WaitForData, the loop terminates |
| 1349 | without releasing the pipe's thread. Release it now. */ |
| 1350 | if (cp->CurrentIndex < KWSYSPE_PIPE_COUNT) { |
| 1351 | KWSYSPE_DEBUG((stderr, "releasing reader %d\n", cp->CurrentIndex)); |
| 1352 | ReleaseSemaphore(cp->Pipe[cp->CurrentIndex].Reader.Go, 1, 0); |
| 1353 | cp->CurrentIndex = KWSYSPE_PIPE_COUNT; |
| 1354 | } |
| 1355 | |
| 1356 | /* Wait for all pipe threads to reset. */ |
| 1357 | for (i = 0; i < KWSYSPE_PIPE_COUNT; ++i) { |
| 1358 | KWSYSPE_DEBUG((stderr, "waiting reader reset %d\n", i)); |
| 1359 | WaitForSingleObject(cp->Pipe[i].Reader.Reset, INFINITE); |
| 1360 | KWSYSPE_DEBUG((stderr, "waiting waker reset %d\n", i)); |
| 1361 | WaitForSingleObject(cp->Pipe[i].Waker.Reset, INFINITE); |
| 1362 | } |
| 1363 | |
| 1364 | /* ---- It is now safe again to call kwsysProcessCleanup. ----- */ |
| 1365 | /* Close all the pipes. */ |
| 1366 | kwsysProcessCleanup(cp, 0); |
| 1367 | |
| 1368 | /* Determine the outcome. */ |
| 1369 | if (cp->Killed) { |
| 1370 | /* We killed the child. */ |
| 1371 | cp->State = kwsysProcess_State_Killed; |
| 1372 | } else if (cp->TimeoutExpired) { |
| 1373 | /* The timeout expired. */ |
| 1374 | cp->State = kwsysProcess_State_Expired; |
| 1375 | } else { |
| 1376 | /* The children exited. Report the outcome of the child processes. */ |
| 1377 | for (i = 0; i < cp->NumberOfCommands; ++i) { |
| 1378 | cp->ProcessResults[i].ExitCode = cp->CommandExitCodes[i]; |
| 1379 | if ((cp->ProcessResults[i].ExitCode & 0xF0000000) == 0xC0000000) { |
| 1380 | /* Child terminated due to exceptional behavior. */ |
| 1381 | cp->ProcessResults[i].State = kwsysProcess_StateByIndex_Exception; |
| 1382 | cp->ProcessResults[i].ExitValue = 1; |
| 1383 | kwsysProcessSetExitExceptionByIndex(cp, cp->ProcessResults[i].ExitCode, |
| 1384 | i); |
| 1385 | } else { |
no test coverage detected
searching dependent graphs…