bin/107171: systat(1) doesn't die when it's xterm is killed
while it's running
Bruce Evans
bde at zeta.org.au
Thu Mar 8 12:30:13 UTC 2007
The following reply was made to PR bin/107171; it has been noted by GNATS.
From: Bruce Evans <bde at zeta.org.au>
To: Nate Eldredge <nge at cs.hmc.edu>
Cc: freebsd-gnats-submit at FreeBSD.org
Subject: Re: bin/107171: systat(1) doesn't die when it's xterm is killed
while it's running
Date: Thu, 8 Mar 2007 23:20:56 +1100 (EST)
On Thu, 8 Mar 2007, Nate Eldredge wrote:
> I presume the retry is to cope with the case where getch() was interrupted
> by a signal. So probably it should only retry if errno = EINTR. This is
> essentially what top does. Also, ferror(stdin) is a bogus test; getch()
> does not go through stdio and so ferror(stdin) will never be set, and the
> clearerr() is bogus too.
>
> EINTR is probably moot for FreeBSD anyway since it appears our ncurses
> handles that transparently, but it doesn't hurt to check.
ncurses has code to actively hide it, but this doesn't seem to be
configured in FreeBSD (option HIDE_EINTR). Thus getch()'s man page
may be wrong in claiming that the ncurses implementation never returns
EINTR.
In fact, it is a bug for getch() to never return EINTR, and a worse
bug to loop in an input function when read() returns EINTR. Most
unthreaded applications that use signal handlers need to change the
BSD default of restarting syscalls after a signal, so that their signal
handlers can just set a flag and depend on their main loop checking
the flag promptly. Restarting syscalls prevents the flag being checked
promptly by looping calling read() (or another syscall) in the kernel,
and HIDE_EINTR would prevent the flag being checked promptly by looping
calling read() in the library.
However, EINTR is probably irrelevant for the current bug. systat
doesn't catch SIGHUP in order to clean up up unsafely like it does
for SIGINT, so any SIGHUP that gives EOF on the terminal would either:
- kill the process uncleanly, or
- not be delivered to the process because it is masked (no EINTR since
it is not caught), or
- not be delivered to the process because of job control stuff.
So systat just needs a simple check for EOF from getch() and the
remainly problem is that getch(), like getc(), unimproves on read()
by not having any way to distinguish the non-error of EOF from errors.
Bruce
More information about the freebsd-bugs
mailing list