Path: utzoo!utgpu!jarvis.csri.toronto.edu!rutgers!usc!polyslo!decwrl!vixie!pacbell!att!cbnews!mark From: mark@cbnews.ATT.COM (Mark Horton) Newsgroups: comp.std.c Subject: how to exit from a signal routine Keywords: ANSI, longjmp, signal Message-ID: <7997@cbnews.ATT.COM> Date: 6 Jul 89 15:42:04 GMT Organization: AT&T Bell Laboratories Lines: 51 Suppose you're writing an application, like ed or vi, that runs interactively at the terminal, but when the user hits DEL, no matter what is going on, it aborts and comes back for another user command. Suppose this program has to be very portable; it must run on System V, Berkeley, ANSI, POSIX, and V7. In the old days, you would catch SIGINT and have the signal handler do a longjmp back to the main loop. Another reasonable approach was to have the signal handler just return, and the read from the tty that was probably interrupted could check to see if read exited with EINTR, and if so print another prompt and go back for another command. Then Berkeley 4.2BSD changed how signal worked, and if the handler returned, the read would just resume. It became accepted wisdom among authors of highly portable programs that the longjmp approach was the most portable method. (Checking, this is true of 4.2BSD and 4.3BSD, but SunOS 4.0 does it the System V way.) Now ANSI C has decreed that you can't call longjmp, or any other function except signal, from inside a signal handler for any signal except those raised by abort, raise, or SIGFPE. The reason given for this is that you might be in the middle of calling that function already when the interrupt comes in, and C library routine are not required to be reentrant. You can't call longjmp to get out of a signal handler because maybe the code was in the middle of calling longjmp when the signal came in. Obscure, but they're right. (On the other hand, I can't see the harm in reentering longjmp, you'll never get back to the first call.) So where does this leave the developer? ANSI C says the only way to exit from a SIGINT handler is to return. The routine is supposed to pick up where it left off, ala 4.2BSD (although the System V behavior of having the read return EINTR seems to be allowed too.) Even if you pretend 4.*BSD doesn't exist, you can imagine the complexity of checking for EINTR after every terminal read, if you call handy stdio routines like getchar, scanf, and fgets. (Nobody calls gets anymore, right? :-) Has anybody found a portable solution to this problem? Is there any conceivable implementation of longjmp that will have problems when it gets called 1 1/2 times? There is a similar problem with trying to call exit from a signal handler. exit flushes all stdio buffers, and you might have been in the middle of an I/O operation when the signal came in. This could cause a core dump in exit! Is this something that should be fixed in the ANSI C standard? Mark Horton