Raphael Quinet wrote: > > [ a cool summary of signals which i'm thinking about to copy for my students :) ] > - SIGILL: one some processors that do not deliver SIGBUS in all cases, > you can get a SIGILL if a pointer to a callback function was > overwritten with garbage. If the pointer is still referencing some > area inside a code segment (so that you don't get a SIGSEGV) but not > pointing to the start of a valid instruction, you will get the SIGILL. > By the way, the Gimp does not catch this one. Why? Dunno, most likely it was just forgotten in the first place. > - SIGABRT: usually triggered by the application calling abort() or by a > user who wants to get a core dump from a running process. It can be > caught by an application that wants to perform some specific cleanup > tasks, but in most cases it should not be caught by a generic error > handler. I don't understand why the Gimp maps this to the generic > gimp_fatal_error() function??? Yep, we should not catch it but let the kernel do it's job. If the user wants a core dump, she should get one. > - 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). However, a signal handler can do whatever it likes with the app's structures as long as it uses atomic data access (which can be a pointer, as pointers have the same size as integers, which are atomic. This is true at least on all processors which have a GNU libc port and finding a processor where pointers are not atomic looks very unlikely to me). The usage of SIGCLD is strongly discouraged by Stevens and some Solaris document I fould recently. But Gimp uses SIGCHLD anyway. > In most of the applications that I wrote, the signal handlers do > nothing directly: they only set a flag that is checked by the main > loop (in an idle function for GTK+ apps, or after poll() or select() > for applications that use low-level calls). I define one flag for > each signal (got_sigchld, got_sigterm, ...) and a master flag that > tells if any of the signal-specific flags have been set. Sometimes I > also use counters instead of boolean flags, but on some systems the > counters are not reliable (especially if there is no SA_NODEFER) so > most of the time they are meaningless. > > 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 :)