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