On Thu, 11 May 2000, Michael Natterer <[EMAIL PROTECTED]> wrote:
> Raphael Quinet wrote:
> > - SIGCHLD or SIGCLD: a child process died.  This signal can be
> >   delivered at any time.  Some systems do not provide a reliable way
> >   to know how many processes exited (if they do not support SA_NODEFER
> >   or if their waitpid() or wait3() calls are broken), so it is usually
> >   better to simply set a flag in the signal handler (without calling
> >   any wait*() function) and to check the status of the children outside
> >   the signal handler, until some wait*() function reports that there
> >   are no more dead processes.  For example:
> >     while ((pid = waitpid (-1, &status, WNOHANG)) > 0)
> >       { ... /* check WIFEXITED(status) and other things */ }
> This is what currently happens (ok, it happens in the handler, but WNOHANG
> *should* be absolutely safe).

No, actually it is not safe on all operating systems: as I wrote
elsewhere, you cannot always rely on SA_NODEFER.  This means that in
some cases, you could miss a SIGCHLD signal that occurs while you are
still inside the handler but after the last test on waitpid().  If
this happens, the main app will not see that one of the plug-ins has
died (until another one dies and the handler collects the status for
both).  That's why it is safer to make the tests outside the signal
handler.  Otherwise, you could have a race condition on some systems
(very seldom, but still...).

> The usage of SIGCLD is strongly discouraged by Stevens and some Solaris
> document I fould recently. But Gimp uses SIGCHLD anyway.

And here is an excerpt from /usr/include/sys/signal.h on Solaris 2.6:

#define SIGCLD  18      /* child status change */
#define SIGCHLD 18      /* child status change alias (POSIX) */

So it does not make much of a difference under recent versions of
Solaris, at least... :-)  But they still say in some docs that the
behavior of SIGCLD might change in future releases, so the POSIX
version should be used in new programs.

> > In one application that wanted to catch SIGSEGV, SIGBUS, SIGILL and
> > SIGFPE, I created a handler that uses a direct call to write() on an
> > fd that was previously obtained from fileno(stderr) (this fd is saved
> > early so that the write() call can work even if the FILE *stderr is
> > overwritten with garbage).  Doing this is safe, AFAIK.
> Yep, write() is safe. Gimp uses g_print() which is not really safe, but
> then we call g_on_error_query() which definitely does a bit more than
> what's allowed :)

Yes...  I wrote a few months ago that I would change that and implement
some kind of --enable-stack-trace option, but I never took the time to
do it.

> >From glib/gerror.c:
> /* 
>  * MT safe ; except for g_on_error_stack_trace, but who wants thread safety 
>  * then
>  */

Note that being MT safe is not enough.  For the 4 signals that are
listed above, you can usually expect that your memory is already
corrupted.  So if you want to minimize the risks of crashing
recursively inside the signal handler, you should avoid using
variables as much as possible.  A handler for SIGSEGV is a good place
for paranoia...

The other signal handlers do not need so much defensive programming.
Being MT safe is usually enough.

> killall -SIGGIMP ps



Reply via email to