On Interix we cannot rely on SIGCHLD because it is only sometimes delivered. Our SIGCHLD handler wakes up any current select() call to check if its child terminated, but the handler itself does not care about any child. Therefore we can use the same handler with SIGALRM to poll at regular intervals.
Patch from Markus Duft, posted to cmake@cmake.org, 2010-02-18. --- Markus Duft wrote: > > with this check it seems that all sub-processes "time out" immediately. On this front, it turns out that you're correct. The polling timeout code path was wrong...in CMake 2.6.4. When I responded before I was looking at the latest development sources which have already fixed the problem by calling GetTimeoutLeft correctly. > > so now i have two patches to make it work - which one should i prefer? Here is a patch based on your sigalrm patch. We can get better than 1 second intervals by using "uslarm()", which I hope exists on Interix. Please build CMake 2.8.0 with this patch and try it. -Brad Source/kwsys/ProcessUNIX.c | 29 +++++++++++++++++++++++++++++ 1 files changed, 29 insertions(+), 0 deletions(-) diff --git a/Source/kwsys/ProcessUNIX.c b/Source/kwsys/ProcessUNIX.c index 373e906..a70c172 100644 --- a/Source/kwsys/ProcessUNIX.c +++ b/Source/kwsys/ProcessUNIX.c @@ -2526,6 +2526,13 @@ static kwsysProcessInstances kwsysProcesses; /* The old SIGCHLD handler. */ static struct sigaction kwsysProcessesOldSigChldAction; +#if defined(__INTERIX) +/* Interix does not deliver SIGCHLD reliably when a child terminates + so we simulate it at regular intervals using SIGALRM. */ +# define KWSYSPE_SIGALRM_INTERVAL 100000 /* usec */ +static struct sigaction kwsysProcessesOldSigAlrmAction; +#endif + /*--------------------------------------------------------------------------*/ static void kwsysProcessesUpdate(kwsysProcessInstances* newProcesses) { @@ -2536,6 +2543,9 @@ static void kwsysProcessesUpdate(kwsysProcessInstances* newProcesses) sigset_t oldset; sigemptyset(&newset); sigaddset(&newset, SIGCHLD); +#if defined(KWSYSPE_SIGALRM_INTERVAL) + sigaddset(&newset, SIGALRM); +#endif sigprocmask(SIG_BLOCK, &newset, &oldset); /* Store the new set in that seen by the signal handler. */ @@ -2642,6 +2652,13 @@ static int kwsysProcessesAdd(kwsysProcess* cp) while((sigaction(SIGCHLD, &newSigChldAction, &kwsysProcessesOldSigChldAction) < 0) && (errno == EINTR)); + +#if defined(KWSYSPE_SIGALRM_INTERVAL) + while((sigaction(SIGALRM, &newSigChldAction, + &kwsysProcessesOldSigAlrmAction) < 0) && + (errno == EINTR)); + ualarm(KWSYSPE_SIGALRM_INTERVAL, KWSYSPE_SIGALRM_INTERVAL); +#endif } } @@ -2680,6 +2697,12 @@ static void kwsysProcessesRemove(kwsysProcess* cp) while((sigaction(SIGCHLD, &kwsysProcessesOldSigChldAction, 0) < 0) && (errno == EINTR)); +#if defined(KWSYSPE_SIGALRM_INTERVAL) + ualarm(0, 0); + while((sigaction(SIGALRM, &kwsysProcessesOldSigAlrmAction, 0) < 0) && + (errno == EINTR)); +#endif + /* Free the table of process pointers since it is now empty. This is safe because the signal handler has been removed. */ newProcesses.Size = 0; @@ -2736,6 +2759,12 @@ static void kwsysProcessesSignalHandler(int signum while((sigaction(SIGCHLD, &newSigChldAction, &kwsysProcessesOldSigChldAction) < 0) && (errno == EINTR)); + +#if defined(KWSYSPE_SIGALRM_INTERVAL) + while((sigaction(SIGALRM, &newSigChldAction, + &kwsysProcessesOldSigAlrmAction) < 0) && + (errno == EINTR)); +#endif } #endif } -- 1.6.6.1 _______________________________________________ Powered by www.kitware.com Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Follow this link to subscribe/unsubscribe: http://www.cmake.org/mailman/listinfo/cmake