[CMake] [PATCH] KWSys: Avoid buggy SIGCHLD on Interix

Markus Duft markus.duft at salomon.at
Tue Feb 23 08:34:24 EST 2010


Markus Duft wrote:
> Brad King wrote:
>> 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.
> 
> the patch is ok as-is now. it fixes my issues on multi-core interix. in
> combination with my interix patch (attached again), interix seems to
> work rather good. i get the following test results (which i find
> surprisingly good, knowing of the many hickups interix can have ;)):
> 
> 97% tests passed, 5 tests failed out of 156
> 
> Total Test time (real) = 2058.00 sec
> 
> The following tests FAILED:
>          49 - ExportImport (Failed)
>          73 - CMakeTestMultipleConfigures (SEGFAULT)
>          96 - Plugin (Failed)
>         106 - CTest.UpdateGIT (Failed)
>         123 - CTestTestTimeout (Failed)
> Errors while running CTest

owh - btw. the results are from 2.8.1 rc3.

> 
> Opinions?
> 
> Thanks!
> 
> Cheers, Markus
> 
>> Patch from Markus Duft, posted to cmake at 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
>>  }
> 
> 
> ------------------------------------------------------------------------
> 
> _______________________________________________
> 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



More information about the CMake mailing list