Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 17 Apr 2012 17:50:04 GMT
From:      Jeremy Chadwick <freebsd@jdc.parodius.com>
To:        freebsd-bugs@FreeBSD.org
Subject:   Fwd: Re: Fwd: Re: bin/161739: top(1): top -b does not restore ICANON and ECHO terminal capabilities when exiting
Message-ID:  <201204171750.q3HHo4ni003536@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR bin/161739; it has been noted by GNATS.

From: Jeremy Chadwick <freebsd@jdc.parodius.com>
To: bug-followup@FreeBSD.org
Cc:  
Subject: Fwd: Re: Fwd: Re: bin/161739: top(1): top -b does not restore ICANON
 and ECHO terminal capabilities when exiting
Date: Tue, 17 Apr 2012 10:40:04 -0700

 Below is an Email I sent kib@ about this problem, as he said he could
 not reproduce it.
 
 I spent 3 hours on this today, writing a debugging routine to print out
 all the internal variables and the terminal structures (termios) to
 find out where the problem lies.
 
 It appears that now the "-b" flag works fine, but "-a" is now broken
 as a result of that commit.
 
 The explanation for what's happening in the code is below.  Someone just
 needs to figure out why is_a_terminal becomes 0 during the program's
 execution (printing output, etc.) because this is what causes the issue.
 
 -- 
 | Jeremy Chadwick                                 jdc@parodius.com |
 | Parodius Networking                     http://www.parodius.com/ |
 | UNIX Systems Administrator                 Mountain View, CA, US |
 | Making life hard for others since 1977.             PGP 4BD6C0CB |
 
 ----- Forwarded message from Jeremy Chadwick <freebsd@jdc.parodius.com> -----
 
 > From: Jeremy Chadwick <freebsd@jdc.parodius.com>
 > To: Konstantin Belousov <kostikbel@gmail.com>
 > Date: Tue, 17 Apr 2012 10:29:33 -0700
 > Subject: Re: Fwd: Re: bin/161739: top(1): top -b does not restore ICANON and ECHO terminal capabilities when exiting
 > 
 > I stand partially corrected -- it looks like your change made recently
 > fixed the problem in the PR for the -b flag only; but now -a has the
 > problem.
 > 
 > I wrote a debug printing routine and shoved it into top.c to look at the
 > results of new_settings and old_settings (termios struct), and also what
 > the current terminal settings are for comparison and some other internal
 > variables which are used to determine when/how to reset the terminal.
 > 
 > There is definitely a problem.
 > 
 > (10:23:01 jdc@omake) ~/usr.bin/top $ ./top -a 2>/tmp/results
 > 
 > {pressed "q" after 1 iteration}
 > 
 > (10:23:18 jdc@omake) ~/usr.bin/top $ (10:23:24 jdc@omake) ~/usr.bin/top $
 > 
 > {I had to type "stty icanon echo" to restore things}
 > 
 > Results:
 > 
 > (10:23:26 jdc@omake) ~/usr.bin/top $ cat /tmp/results
 > DEBUG: before init_termcap
 > DEBUG: is_a_terminal  = 0
 > DEBUG: smart_terminal = 0
 > DEBUG: interactive    = 2 (Maybe)
 > DEBUG: displays       = 0
 > DEBUG: old_settings:
 > DEBUG:   c_iflag = 0x0
 > DEBUG:   c_oflag = 0x0
 > DEBUG:   c_cflag = 0x0
 > DEBUG:   c_lflag = 0x0 ()
 > DEBUG: new_settings:
 > DEBUG:   c_iflag = 0x0
 > DEBUG:   c_oflag = 0x0
 > DEBUG:   c_cflag = 0x0
 > DEBUG:   c_lflag = 0x0 ()
 > DEBUG: current terminal settings:
 > DEBUG:   c_iflag = 0x2b02
 > DEBUG:   c_oflag = 0x3
 > DEBUG:   c_cflag = 0x4b00
 > DEBUG:   c_lflag = 0x5cb (ECHOKE,ECHOE,ECHO,ECHOCTL,ISIG,ICANON,IEXTEN,)
 > ----------------------------------------
 > DEBUG: after init_termcap
 > DEBUG: is_a_terminal  = 0
 > DEBUG: smart_terminal = 1
 > DEBUG: interactive    = 2 (Maybe)
 > DEBUG: displays       = 0
 > DEBUG: old_settings:
 > DEBUG:   c_iflag = 0x2b02
 > DEBUG:   c_oflag = 0x3
 > DEBUG:   c_cflag = 0x4b00
 > DEBUG:   c_lflag = 0x5cb (ECHOKE,ECHOE,ECHO,ECHOCTL,ISIG,ICANON,IEXTEN,)
 > DEBUG: new_settings:
 > DEBUG:   c_iflag = 0x0
 > DEBUG:   c_oflag = 0x0
 > DEBUG:   c_cflag = 0x0
 > DEBUG:   c_lflag = 0x0 ()
 > DEBUG: current terminal settings:
 > DEBUG:   c_iflag = 0x2b02
 > DEBUG:   c_oflag = 0x3
 > DEBUG:   c_cflag = 0x4b00
 > DEBUG:   c_lflag = 0x5cb (ECHOKE,ECHOE,ECHO,ECHOCTL,ISIG,ICANON,IEXTEN,)
 > ----------------------------------------
 > DEBUG: before init_screen
 > DEBUG: is_a_terminal  = 0
 > DEBUG: smart_terminal = 1
 > DEBUG: interactive    = 1 (Yes)
 > DEBUG: displays       = -1
 > DEBUG: old_settings:
 > DEBUG:   c_iflag = 0x2b02
 > DEBUG:   c_oflag = 0x3
 > DEBUG:   c_cflag = 0x4b00
 > DEBUG:   c_lflag = 0x5cb (ECHOKE,ECHOE,ECHO,ECHOCTL,ISIG,ICANON,IEXTEN,)
 > DEBUG: new_settings:
 > DEBUG:   c_iflag = 0x0
 > DEBUG:   c_oflag = 0x0
 > DEBUG:   c_cflag = 0x0
 > DEBUG:   c_lflag = 0x0 ()
 > DEBUG: current terminal settings:
 > DEBUG:   c_iflag = 0x2b02
 > DEBUG:   c_oflag = 0x3
 > DEBUG:   c_cflag = 0x4b00
 > DEBUG:   c_lflag = 0x5cb (ECHOKE,ECHOE,ECHO,ECHOCTL,ISIG,ICANON,IEXTEN,)
 > ----------------------------------------
 > DEBUG: after init_screen
 > DEBUG: is_a_terminal  = 1
 > DEBUG: smart_terminal = 1
 > DEBUG: interactive    = 1 (Yes)
 > DEBUG: displays       = -1
 > DEBUG: old_settings:
 > DEBUG:   c_iflag = 0x2b02
 > DEBUG:   c_oflag = 0x3
 > DEBUG:   c_cflag = 0x4b00
 > DEBUG:   c_lflag = 0x5cb (ECHOKE,ECHOE,ECHO,ECHOCTL,ISIG,ICANON,IEXTEN,)
 > DEBUG: new_settings:
 > DEBUG:   c_iflag = 0x2b02
 > DEBUG:   c_oflag = 0x3
 > DEBUG:   c_cflag = 0x4b00
 > DEBUG:   c_lflag = 0x4c3 (ECHOKE,ECHOE,ECHOCTL,ISIG,IEXTEN,)
 > DEBUG: current terminal settings:
 > DEBUG:   c_iflag = 0x2b02
 > DEBUG:   c_oflag = 0x3
 > DEBUG:   c_cflag = 0x4b00
 > DEBUG:   c_lflag = 0x4c3 (ECHOKE,ECHOE,ECHOCTL,ISIG,IEXTEN,)
 > ----------------------------------------
 > DEBUG: within quit(), before end_screen
 > DEBUG: is_a_terminal  = 0
 > DEBUG: smart_terminal = 1
 > DEBUG: interactive    = 1 (Yes)
 > DEBUG: displays       = -1
 > DEBUG: old_settings:
 > DEBUG:   c_iflag = 0x2b02
 > DEBUG:   c_oflag = 0x3
 > DEBUG:   c_cflag = 0x4b00
 > DEBUG:   c_lflag = 0x5cb (ECHOKE,ECHOE,ECHO,ECHOCTL,ISIG,ICANON,IEXTEN,)
 > DEBUG: new_settings:
 > DEBUG:   c_iflag = 0x2b02
 > DEBUG:   c_oflag = 0x3
 > DEBUG:   c_cflag = 0x4b00
 > DEBUG:   c_lflag = 0x4c3 (ECHOKE,ECHOE,ECHOCTL,ISIG,IEXTEN,)
 > DEBUG: current terminal settings:
 > DEBUG:   c_iflag = 0x2b02
 > DEBUG:   c_oflag = 0x3
 > DEBUG:   c_cflag = 0x4b00
 > DEBUG:   c_lflag = 0x4c3 (ECHOKE,ECHOE,ECHOCTL,ISIG,IEXTEN,)
 > ----------------------------------------
 > DEBUG: within quit(), after end_screen
 > DEBUG: is_a_terminal  = 0
 > DEBUG: smart_terminal = 1
 > DEBUG: interactive    = 1 (Yes)
 > DEBUG: displays       = -1
 > DEBUG: old_settings:
 > DEBUG:   c_iflag = 0x2b02
 > DEBUG:   c_oflag = 0x3
 > DEBUG:   c_cflag = 0x4b00
 > DEBUG:   c_lflag = 0x5cb (ECHOKE,ECHOE,ECHO,ECHOCTL,ISIG,ICANON,IEXTEN,)
 > DEBUG: new_settings:
 > DEBUG:   c_iflag = 0x2b02
 > DEBUG:   c_oflag = 0x3
 > DEBUG:   c_cflag = 0x4b00
 > DEBUG:   c_lflag = 0x4c3 (ECHOKE,ECHOE,ECHOCTL,ISIG,IEXTEN,)
 > DEBUG: current terminal settings:
 > DEBUG:   c_iflag = 0x2b02
 > DEBUG:   c_oflag = 0x3
 > DEBUG:   c_cflag = 0x4b00
 > DEBUG:   c_lflag = 0x4c3 (ECHOKE,ECHOE,ECHOCTL,ISIG,IEXTEN,)
 > ----------------------------------------
 > 
 > Based on this, you can see that the tcsetattr() call to restore the
 > terminal from old_settings isn't happening.  That call is done in
 > end_screen().
 > 
 > The conditional for that to happen or not is based on the is_a_terminal
 > variable.  And as you can see, is_a_terminal is 0 when end_screen()
 > is called.
 > 
 > You can see that is_a_terminal == 1 after init_screen() is called,
 > but within quit() (but before end_screen()) somehow is_a_terminal
 > is getting reset to 0.  This is what causes the problem.
 > 
 > If you want the patch to see the debug info, let me know.
 > 
 > -- 
 > | Jeremy Chadwick                                 jdc@parodius.com |
 > | Parodius Networking                     http://www.parodius.com/ |
 > | UNIX Systems Administrator                 Mountain View, CA, US |
 > | Making life hard for others since 1977.             PGP 4BD6C0CB |
 > 
 > On Tue, Apr 17, 2012 at 08:28:36AM -0700, Jeremy Chadwick wrote:
 > > (08:22:23 jdc@omake) ~ $ egrep -r -n '(ICANON|ECHO)' /usr/src/contrib/top
 > > /usr/src/contrib/top/screen.c:250:      new_settings.sg_flags &= ~(ECHO|XTABS);
 > > /usr/src/contrib/top/screen.c:278:      /* turn off ICANON, character echo and tab expansion */
 > > /usr/src/contrib/top/screen.c:279:      new_settings.c_lflag &= ~(ICANON|ECHO);
 > > /usr/src/contrib/top/screen.c:302:      /* turn off ICANON, character echo and tab expansion */
 > > /usr/src/contrib/top/screen.c:303:      new_settings.c_lflag &= ~(ICANON|ECHO);
 > > 
 > > So it looks to me like these capabilities aren't being restored
 > > prior to top exiting.  It used to be this way with just "-b", but
 > > now affects "-a" as well.
 > > 
 > > All of those lines are part of init_screen().  However this routine
 > > is filled with #ifdefs.
 > > 
 > > end_screen() has some generic attempt to reset these capabilities
 > > (variable is called old_settings.
 > > 
 > > Possibly the issue is with some kind of code logic bug pertaining to
 > > is_a_terminal or smart_terminal.
 > > 
 > > -- 
 > > | Jeremy Chadwick                                 jdc@parodius.com |
 > > | Parodius Networking                     http://www.parodius.com/ |
 > > | UNIX Systems Administrator                 Mountain View, CA, US |
 > > | Making life hard for others since 1977.             PGP 4BD6C0CB |
 > > 
 > > On Tue, Apr 17, 2012 at 08:19:29AM -0700, Jeremy Chadwick wrote:
 > > > On Tue, Apr 17, 2012 at 12:36:38PM +0300, Konstantin Belousov wrote:
 > > > > On Mon, Apr 16, 2012 at 02:48:33PM -0700, Jeremy Chadwick wrote:
 > > > > > Kostik,
 > > > > > 
 > > > > > Please see the below PR.  I believe you've introduced a problem that
 > > > > > used to just affect the -b flag, but now affects -a as well.
 > > > > > 
 > > > > > Maybe you can fix both.  :-)
 > > > > I cannot reproduce the problem.
 > > > 
 > > > On what, RELENG_9 or what?  This is easily reproducible on every
 > > > RELENG_8 system we have, as well as my home workstation, and a RELENG_8
 > > > FreeBSD instance run under VMware.
 > > > 
 > > > (08:16:25 jdc@omake) ~ $ stty -a
 > > > speed 9600 baud; 43 rows; 132 columns;
 > > > lflags: icanon isig iexten echo echoe -echok echoke -echonl echoctl
 > > >         -echoprt -altwerase -noflsh -tostop -flusho -pendin -nokerninfo
 > > >         -extproc
 > > > iflags: -istrip icrnl -inlcr -igncr ixon -ixoff ixany imaxbel -ignbrk
 > > >         brkint -inpck -ignpar -parmrk
 > > > oflags: opost onlcr -ocrnl tab0 -onocr -onlret
 > > > cflags: cread cs8 -parenb -parodd hupcl -clocal -cstopb -crtscts -dsrflow
 > > >         -dtrflow -mdmbuf
 > > > cchars: discard = ^O; dsusp = ^Y; eof = ^D; eol = <undef>;
 > > >         eol2 = <undef>; erase = ^?; erase2 = ^H; intr = ^C; kill = ^U;
 > > >         lnext = ^V; min = 1; quit = ^\; reprint = ^R; start = ^Q;
 > > >         status = ^T; stop = ^S; susp = ^Z; time = 0; werase = ^W;
 > > > 
 > > > (08:16:27 jdc@omake) ~ $ top -a
 > > > last pid: 62310;  load averages:  0.00,  0.00,  0.00                                                        up 1+11:03:16  08:16:30
 > > > 32 processes:  1 running, 31 sleeping
 > > > CPU:     % user,     % nice,     % system,     % interrupt,     % idle
 > > > Mem: 168M Active, 333M Inact, 375M Wired, 236K Cache, 389M Buf, 2764M Free
 > > > Swap: 8192M Total, 8192M Free
 > > > 
 > > >   PID USERNAME  THR PRI NICE   SIZE    RES STATE   C   TIME   WCPU COMMAND
 > > >  6482 halbot      1  44    0 90940K 75900K select  0   0:14  0.00% /usr/local/bin/perl /home/halbot/hal/halbot.pl /home/halbot/
 > > >   575 root        1  44    0  6900K  1272K select  0   0:06  0.00% /usr/sbin/powerd
 > > > 19810 root        1  44    0 73092K 43876K select  0   0:04  0.00% /usr/local/bin/spamd -c --min-children=4 --min-spare=4 --max
 > > >   572 root        1  44    0 11788K  2560K select  0   0:02  0.00% /usr/sbin/ntpd -c /conf/ME/ntp.conf -p /var/run/ntpd.pid -f
 > > >   362 _pflogd     1  44    0  8116K  1676K bpf     0   0:01  0.00% pflogd: [running] -s 116 -i pflog0 -f /var/log/pflog (pflogd
 > > > 19811 root        1  44    0 75140K 46620K select  0   0:01  0.00% spamd child (perl)
 > > >   657 root        1  44    0 11228K  2832K kqread  2   0:01  0.00% /usr/local/libexec/postfix/master
 > > > 58324 root        1  44    0 10436K  2344K kqread  2   0:00  0.00% /usr/local/sbin/dovecot -c /conf/ME/mail/dovecot.conf
 > > > 19812 root        1  44    0 73092K 44712K select  1   0:00  0.00% spamd child (perl)
 > > >   672 root        1  44    0  7960K  1600K nanslp  0   0:00  0.00% /usr/sbin/cron -s
 > > >   493 root        1  44    0  6904K  1516K select  0   0:00  0.00% /usr/sbin/syslogd -s
 > > >  5912 bind        7  44    0 28836K 18248K kqread  0   0:00  0.00% /usr/sbin/named -t /var/named -u bind
 > > > 58325 dovecot     1  44    0 10432K  1980K kqread  0   0:00  0.00% dovecot/anvil
 > > > 58326 root        1  44    0 10436K  1960K kqread  1   0:00  0.00% dovecot/log
 > > >   663 postfix     1  44    0 11228K  2952K kqread  1   0:00  0.00% qmgr -l -t fifo -u
 > > > 19813 root        1  44    0 73092K 43876K select  2   0:00  0.00% spamd child (perl)
 > > > 19815 root        1  44    0 73092K 43876K select  3   0:00  0.00% spamd child (perl)
 > > > 19814 root        1  44    0 73092K 43876K select  2   0:00  0.00% spamd child (perl)
 > > > 62304 root        1  45    0 18980K  4048K sbwait  2   0:00  0.00% sshd: jdc [priv] (sshd)
 > > > 62302 root        1  45    0 12676K  2544K kqread  0   0:00  0.00% dovecot/auth -w
 > > > 62300 dovecot     1  44    0 12640K  2480K kqread  3   0:00  0.00% dovecot/auth
 > > >   668 root        1  44    0 16420K  3716K select  1   0:00  0.00% /usr/sbin/sshd
 > > > 62307 jdc         1  44    0 10228K  2868K wait    1   0:00  0.00% -bash (bash)
 > > > 62299 root        1  44    0 10432K  2900K kqread  1   0:00  0.00% dovecot/config
 > > > 62306 jdc         1  44    0 18980K  4132K select  1   0:00  0.00% sshd: jdc@pts/0 (sshd)
 > > > 62309 postfix     1  44    0 11232K  2984K kqread  0   0:00  0.00% pickup -l -t fifo -u
 > > > 62301 root        1  44    0 13124K  2644K kqread  0   0:00  0.00% dovecot/ssl-params
 > > > 62310 jdc         1  44    0  9356K  2084K CPU0    0   0:00  0.00% top -a
 > > >   702 root        1  44    0  9008K  1636K select  1   0:00  0.00% /usr/sbin/inetd -C 0
 > > >   360 root        1  76    0  8116K  1636K sbwait  1   0:00  0.00% pflogd: [priv] (pflogd)
 > > >   721 root        1  76    0  6900K  1268K ttyin   1   0:00  0.00% /usr/libexec/getty Pc ttyv0
 > > >   722 root        1  76    0  6900K  1268K ttyin   0   0:00  0.00% /usr/libexec/getty Pc ttyv1
 > > > 
 > > > 
 > > > 
 > > > (08:16:31 jdc@omake) ~ $ speed 9600 baud; 43 rows; 132 columns;
 > > > lflags: -icanon isig iexten -echo echoe -echok echoke -echonl echoctl
 > > >         -echoprt -altwerase -noflsh -tostop -flusho -pendin -nokerninfo
 > > >         -extproc
 > > > iflags: -istrip icrnl -inlcr -igncr ixon -ixoff ixany imaxbel -ignbrk
 > > >         brkint -inpck -ignpar -parmrk
 > > > oflags: opost onlcr -ocrnl tab0 -onocr -onlret
 > > > cflags: cread cs8 -parenb -parodd hupcl -clocal -cstopb -crtscts -dsrflow
 > > >         -dtrflow -mdmbuf
 > > > cchars: discard = ^O; dsusp = ^Y; eof = ^D; eol = <undef>;
 > > >         eol2 = <undef>; erase = ^?; erase2 = ^H; intr = ^C; kill = ^U;
 > > >         lnext = ^V; min = 1; quit = ^\; reprint = ^R; start = ^Q;
 > > >         status = ^T; stop = ^S; susp = ^Z; time = 0; werase = ^W;
 > > > 
 > > > 
 > > > All I did was hit "q" to exit top, then typed "stty -a".  None of my
 > > > input was echo'd back to the terminal, which is why you seed the "speed
 > > > 9600 baud ..." on the same line as my shell.
 > > > 
 > > > Note the -icanon and -echo capabilities shown there, while prior to
 > > > running top, they aren't "-" (meaning icanon and echo are enabled).
 > > > 
 > > > -- 
 > > > | Jeremy Chadwick                                 jdc@parodius.com |
 > > > | Parodius Networking                     http://www.parodius.com/ |
 > > > | UNIX Systems Administrator                 Mountain View, CA, US |
 > > > | Making life hard for others since 1977.             PGP 4BD6C0CB |
 > > > 
 
 ----- End forwarded message -----



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201204171750.q3HHo4ni003536>