battle@alphard.cs.utk.edu (David Battle) (01/03/90)
I like to run an instance of "top" in a window of its own started from my ".xsession" file and using the "-e" option of xterm. The problem is that when I log out, the window goes away, but the "top" keeps running, spewing output to whatever pseudo-tty the window was attached to. I am currently killing it by grep'ing through the output of "ps" and killing processes whose command strings begin with "top". Is there a better way to do this? David L. Battle battle@battle.esd.ornl.gov battle@utkux1.utk.edu battle@utkvx2.BITNET
casey@gauss.llnl.gov (Casey Leedom) (01/03/90)
| From: battle@alphard.cs.utk.edu (David Battle) | | I like to run an instance of "top" in a window of its own started from my | ".xsession" file and using the "-e" option of xterm. The problem is that | when I log out, the window goes away, but the "top" keeps running, spewing | output to whatever pseudo-tty the window was attached to. I am currently | killing it by grep'ing through the output of "ps" and killing processes | whose command strings begin with "top". Is there a better way to do this? Actually, I think it tries but is getting EIO errors since there's no process on the master side of the pseudo tty. I know that it gets EIO errors when it tries to read from the slave side of the pseudo tty. However, when I started up a second xterm, it started getting some of the output of the rogue top process. (After checking the xterm sources I see that it only uses vhangup(2) to ensure a ``clean'' tty on SYSV systems. Is there any reason for this? Why isn't vhangup(2) being used on BSD systems? Is this a ``fixed in R4'' bug?) When xterm exits, it does two fundamental things to notify processes using the window pseudo tty: 1. it sends a SIGHUP to the process group named by the PID of the original xterm child process started up under the window and 2. it closes its [master] end of the pseudo tty. If the process(es) are set up to deal the effects with either or both actions, then things should be cleaned up fairly nicely. In particular, if the xterm child process is a shell, it's the responsibility of the shell to pass the SIGHUP on to the shell's child processes that are using the pseudo tty. (This propagation isn't done typically for shell descendents which are running in the background, but as noted above, subsequent xterms which end up using the pseudo tty and don't perform a vhangup will end up getting any output those shell descendents end up generating. For further problems and limitations of vhangup, see the vhangup(2) manual page.) As it turns out, top, vi and several other programs, don't deal with either SIGHUPS or EIOs generated from trying to access a pseudo tty whose master end has been closed. Patching top to deal with either fixes the problem you have described. Following is a patch for top that addresses both. My sources say that I have version 2.5 of top. *** top.c-dist Mon Jan 9 20:03:47 1989 --- top.c Tue Jan 2 14:41:28 1990 *************** *** 270,275 **** --- 270,276 ---- char ch; char *iptr; char no_command = 1; + int ioerr; int readfds; struct timeval timeout; static char command_chars[] = "\f qh?en#sdkr"; *************** *** 572,577 **** --- 573,579 ---- old_sigmask = sigblock(Smask(SIGINT) | Smask(SIGQUIT) | Smask(SIGTSTP)); #endif init_screen(); + (void) signal(SIGHUP, leave); (void) signal(SIGINT, leave); (void) signal(SIGQUIT, leave); (void) signal(SIGTSTP, tstop); *************** *** 831,837 **** timeout.tv_usec = 0; /* wait for either input or the end of the delay period */ ! if (select(32, &readfds, (int *)NULL, (int *)NULL, &timeout) > 0) { int newval; char *errmsg; --- 833,842 ---- timeout.tv_usec = 0; /* wait for either input or the end of the delay period */ ! ioerr = select(32, &readfds, (int *)NULL, (int *)NULL, &timeout); ! if (ioerr < 0) ! quit(EIO); ! if (ioerr > 0) { int newval; char *errmsg; *************** *** 841,847 **** /* now read it and convert to command index */ /* (use "change" as a temporary to hold index) */ ! (void) read(0, &ch, 1); if ((iptr = index(command_chars, ch)) == NULL) { /* illegal command */ --- 846,853 ---- /* now read it and convert to command index */ /* (use "change" as a temporary to hold index) */ ! if (read(0, &ch, 1) <= 0) ! quit(EIO); if ((iptr = index(command_chars, ch)) == NULL) { /* illegal command */ *************** *** 892,898 **** show_help(); standout("Hit any key to continue: "); fflush(stdout); ! (void) read(0, &ch, 1); break; case CMD_errors: /* show errors */ --- 898,905 ---- show_help(); standout("Hit any key to continue: "); fflush(stdout); ! if (read(0, &ch, 1) <= 0) ! quit(EIO); break; case CMD_errors: /* show errors */ *************** *** 910,916 **** show_errors(); standout("Hit any key to continue: "); fflush(stdout); ! (void) read(0, &ch, 1); } break; --- 917,924 ---- show_errors(); standout("Hit any key to continue: "); fflush(stdout); ! if (read(0, &ch, 1) <= 0) ! quit(EIO); } break; *** display.c-dist Sat Jun 10 13:43:59 1989 --- display.c Tue Jan 2 14:19:17 1990 *************** *** 826,837 **** register char ch; register char cnt = 0; register char maxcnt = 0; /* allow room for null terminator */ size -= 1; /* read loop */ ! while ((fflush(stdout), read(0, ptr, 1) > 0)) { /* newline means we are done */ if ((ch = *ptr) == '\n') --- 826,838 ---- register char ch; register char cnt = 0; register char maxcnt = 0; + int ioerr; /* allow room for null terminator */ size -= 1; /* read loop */ ! while ((fflush(stdout), (ioerr = read(0, ptr, 1)) > 0)) { /* newline means we are done */ if ((ch = *ptr) == '\n') *************** *** 887,892 **** --- 888,896 ---- } } } + + if (ioerr < 0) + quit(EIO); /* all done -- null terminate the string */ *ptr = '\0';