Date: Thu, 3 Mar 2005 03:50:19 GMT From: Bruce Evans <bde@zeta.org.au> To: freebsd-bugs@FreeBSD.org Subject: Re: bin/78304: Signal handler abuse in comsat(8) Message-ID: <200503030350.j233oJ6i070594@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
The following reply was made to PR bin/78304; it has been noted by GNATS. From: Bruce Evans <bde@zeta.org.au> To: Gavin Atkinson <gavin.atkinson@ury.york.ac.uk> Cc: FreeBSD-gnats-submit@freebsd.org Subject: Re: bin/78304: Signal handler abuse in comsat(8) Date: Thu, 3 Mar 2005 14:41:52 +1100 (EST) On Wed, 2 Mar 2005, Gavin Atkinson wrote: >> Description: > > I've been inspired by the talk given by Henning Brauer given at > the UKUUG Winter 2005 on writing safe signal handlers, and have set about > fixing some of them in the FreeBSD source tree. In case you fix lots of these... > while the main routine is already in the memory allocator. This latter > signal has been fixed to simply set a flag, which is now polled and acted > upon in the main loop. ... note that simply setting a flag is usually simply wrong, since FreeBSD has restartable syscalls, restarting syscalls after a signal is the default for signal(2), and most applications and libraries don't handle changing the default using siginterrupt(3) or not setting the default using sigaction(2) (!SA_RESTART). Restarting syscalls can result in the poll in the main loop never being reached, since a syscall can wait forever. Examples of utilities whose signal handling bugs have been moved by simply setting a flag: - ping(8). ping's fixes are not so simple but don't quite work. The resolver library sometimes hangs, and SIGINT to abort ping doesn't work because the resolver library restarts. In this case, the relevant syscall is select() or kevent() so it isn't automatically restarted, and callers of these syscalls must actually do something about EINTR, but the resolver library doesn't know what to do and always restarts. - top(1). top was changed to simply set a flag. It now hangs in a read() from a terminal in some contexts. It then appears to ignore SIGINT, but when you enter something the read completes, control returns to the level that polls the flag, and the SIGINT actually terminates the program. Fixing this in large programs is hard, but comsat seems to be simple enough to fix or to verify that there is no problem. Fixing a large program seems to require never using automatic restarts for syscalls and then fixing all the bugs exposed by this, perhaps starting with the one in stdio (there is a PR about at least 1). Bruce
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200503030350.j233oJ6i070594>