From owner-freebsd-bugs@FreeBSD.ORG Thu Mar 8 10:40:10 2007 Return-Path: X-Original-To: freebsd-bugs@hub.freebsd.org Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 1488016A401 for ; Thu, 8 Mar 2007 10:40:10 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [69.147.83.40]) by mx1.freebsd.org (Postfix) with ESMTP id B25EC13C46B for ; Thu, 8 Mar 2007 10:40:09 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.13.4/8.13.4) with ESMTP id l28Ae9AS095808 for ; Thu, 8 Mar 2007 10:40:09 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.13.4/8.13.4/Submit) id l28Ae9RA095807; Thu, 8 Mar 2007 10:40:09 GMT (envelope-from gnats) Date: Thu, 8 Mar 2007 10:40:09 GMT Message-Id: <200703081040.l28Ae9RA095807@freefall.freebsd.org> To: freebsd-bugs@FreeBSD.org From: Nate Eldredge Cc: Subject: Re: bin/107171: systat(1) doesn't die when it's xterm is killed while it's running X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: Nate Eldredge List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 08 Mar 2007 10:40:10 -0000 The following reply was made to PR bin/107171; it has been noted by GNATS. From: Nate Eldredge To: bug-followup@FreeBSD.org, josh@tcbug.org Cc: Subject: Re: bin/107171: systat(1) doesn't die when it's xterm is killed while it's running Date: Thu, 8 Mar 2007 02:06:35 -0800 (PST) The bug is in /usr/src/usr.bin/systat/keyboard.c, where an error return by getch() is ignored. When you close an xterm, it sends SIGHUP to all processes running on that terminal, and all further terminal I/O by those processes fails with ENXIO. But a process running as a different user (e.g. root) can't receive the SIGHUP, and systat ignores the ENXIO and retries endlessly. 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. Here is a patch which fixes the problem. It still assumes the constant ERR returned by getch() is -1 which is not great style, but I'll touch as little as possible here. --- /usr/src/usr.bin/systat/keyboard.c.old Thu Mar 8 02:00:35 2007 +++ /usr/src/usr.bin/systat/keyboard.c Thu Mar 8 02:00:40 2007 @@ -42,6 +42,7 @@ #include #include #include +#include #include "systat.h" #include "extern.h" @@ -58,9 +59,11 @@ do { refresh(); ch = getch() & 0177; - if (ch == 0177 && ferror(stdin)) { - clearerr(stdin); - continue; + if (ch == 0177) { + if (errno == EINTR) + continue; + else + die(0); } if (ch >= 'A' && ch <= 'Z') ch += 'a' - 'A'; -- Nate Eldredge nge@cs.hmc.edu