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

Markus Duft markus.duft at salomon.at
Fri Feb 19 09:25:02 EST 2010


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.
> 
> 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.

ah, ok :)

> 
>>> 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.

at least the man page and signature in unistd.h exists :) looks good for
that.

> 
> Please build CMake 2.8.0 with this patch and try it.

ok, i hope i'll have time for this tomorrow. i'll report back.

Markus

> 
> -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
>  }



More information about the CMake mailing list