2003-02-14 20:11:20

by Russell King

[permalink] [raw]
Subject: RFC/CFT 1/1: SIGWINCH - behaviour change

I keep on tripping over an annoying "feature" of our tty layer - if
you have a session running with multiple jobs (eg, three ssh sessions)
and you resize the window, SIGWINCH is only sent to the foreground
process, be it the shell, or one of the ssh sessions.

This means if you perform the following actions in order:

- open window.
- start two telnet sessions, suspending the first.
- resize the window.

the active telnet session gets the right terminal size on the remote
pty, and is reflected under bash.

- suspend the current telnet, resume the first session.

this session has the wrong terminal size on the remote pty because
the telnet process didn't get the SIGWINCH.

openssh doesn't seem to suffer from this because it always checks
the window size after resuming; I guess someone reported it as a
bug against openssh.

A similar thing happens when bash isn't running in the foreground
either; however since bash neither automatically check the window
size when commands complete nor listens for SIGWINCH during command
execution, this patch doesn't solve this problem. I believe there
is an option which can be set to correct this though.

POSIX doesn't appear to specify to which processes SIGWINCH is
sent, so here's a patch which sends SIGWINCH to the session rather
than the process group.

Comments? Should bash and telnet be fixed (if we care about telnet
anymore)?

--- orig/drivers/char/tty_io.c Fri Feb 14 16:31:25 2003
+++ linux/drivers/char/tty_io.c Fri Feb 14 19:57:52 2003
@@ -1503,10 +1503,17 @@
return 0;
}

+/*
+ * In the case of pty's, "tty" is the master side
+ * and "real_tty" is the slave side.
+ */
static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty,
struct winsize * arg)
{
struct winsize tmp_ws;
+ struct task_struct *p;
+ struct list_head *l;
+ struct pid *pid;

if (copy_from_user(&tmp_ws, arg, sizeof(*arg)))
return -EFAULT;
@@ -1521,8 +1528,21 @@
#endif
if (tty->pgrp > 0)
kill_pg(tty->pgrp, SIGWINCH, 1);
- if ((real_tty->pgrp != tty->pgrp) && (real_tty->pgrp > 0))
- kill_pg(real_tty->pgrp, SIGWINCH, 1);
+
+ /*
+ * Send SIGWINCH to the whole session on the slave tty.
+ * However, in the case of slave pty's, be careful not
+ * to send two SIGWINCH to the same process group.
+ */
+ if (real_tty->session > 0) {
+ read_lock(&tasklist_lock);
+ for_each_task_pid(real_tty->session, PIDTYPE_SID, p, l, pid) {
+ if (p->pgrp != tty->pgrp)
+ group_send_sig_info(SIGWINCH, (void *)1L, p);
+ }
+ read_unlock(&tasklist_lock);
+ }
+
tty->winsize = tmp_ws;
real_tty->winsize = tmp_ws;
return 0;

--
Russell King ([email protected]) The developer of ARM Linux
http://www.arm.linux.org.uk/personal/aboutme.html


2003-02-14 20:24:30

by John Bradford

[permalink] [raw]
Subject: Re: RFC/CFT 1/1: SIGWINCH - behaviour change

> I keep on tripping over an annoying "feature" of our tty layer - if
> you have a session running with multiple jobs (eg, three ssh sessions)
> and you resize the window, SIGWINCH is only sent to the foreground
> process, be it the shell, or one of the ssh sessions.

This reminds me of a problem I had, which I'd forgotten about, maybe
it's related:

I was using a 7N1, (that's not a typo, it really was 7N1), 9600 bps
serial terminal, and from the shell prompt I connected to a remote
machine using 8N1. I logged in successfully, but the shell didn't
work, yet setting the local serial terminal to 8N1 made it work (!).
After logging out from the remote machine, I had to set the serial
terminal back to 7N1 to use the local machine.

Can anybody else reproduce this? My serial terminal is currently out
of service, (needs some wires soldered on a DB9 connector :-) ).

John.

2003-02-14 21:13:15

by John Bradford

[permalink] [raw]
Subject: Re: RFC/CFT 1/1: SIGWINCH - behaviour change

> > > I keep on tripping over an annoying "feature" of our tty layer - if
> > > you have a session running with multiple jobs (eg, three ssh sessions)
> > > and you resize the window, SIGWINCH is only sent to the foreground
> > > process, be it the shell, or one of the ssh sessions.
> >
> > This reminds me of a problem I had, which I'd forgotten about, maybe
> > it's related:
> >
> > I was using a 7N1, (that's not a typo, it really was 7N1), 9600 bps
> > serial terminal, and from the shell prompt I connected to a remote
> > machine using 8N1. I logged in successfully, but the shell didn't
> > work, yet setting the local serial terminal to 8N1 made it work (!).
> > After logging out from the remote machine, I had to set the serial
> > terminal back to 7N1 to use the local machine.
> >
> > Can anybody else reproduce this? My serial terminal is currently out
> > of service, (needs some wires soldered on a DB9 connector :-) ).
>
> I believe this is "normal" :-)
>
> The remote machine was actually handling 8N0.. so 7N1 was treated
> as 8P0 OR 8N0... The shell didn't work because it was possible to have
> "mark" parity, and the parity errors would show up preventing the bytes
> from being used (mark parity/or parity errors always showed up in the
> most significant bit of the character). Everything looks fine, but wouldn't
> work.
>
> Setting the 8N1 forces the parity bit to zero, but including 8 data bits
> and one stop bit. 7N1 is the same as 8N0, with the parity showing up as
> the 8th bit. The remote (if missing a stop bit) would complete by adding
> a "parity" bit...

Hmmm, I understand how 7N1 looks the same as 8P0 on the wire, but
surely the remote machine should never get to see that, and the local
shell works fine.

-------- ---------- --------------
|Terminal|==7N1==|My machine|--TCP/IP--|Remote machine|
-------- ---------- --------------

If I send an A, although my terminal is sending:

..111111111111101000001111111...
^ ^
Start Stop

my machine will just send a 65 over the TCP/IP connection.

John.

2003-02-14 21:41:16

by Jesse Pollard

[permalink] [raw]
Subject: Re: RFC/CFT 1/1: SIGWINCH - behaviour change

On Friday 14 February 2003 02:35 pm, John Bradford wrote:
> > I keep on tripping over an annoying "feature" of our tty layer - if
> > you have a session running with multiple jobs (eg, three ssh sessions)
> > and you resize the window, SIGWINCH is only sent to the foreground
> > process, be it the shell, or one of the ssh sessions.
>
> This reminds me of a problem I had, which I'd forgotten about, maybe
> it's related:
>
> I was using a 7N1, (that's not a typo, it really was 7N1), 9600 bps
> serial terminal, and from the shell prompt I connected to a remote
> machine using 8N1. I logged in successfully, but the shell didn't
> work, yet setting the local serial terminal to 8N1 made it work (!).
> After logging out from the remote machine, I had to set the serial
> terminal back to 7N1 to use the local machine.
>
> Can anybody else reproduce this? My serial terminal is currently out
> of service, (needs some wires soldered on a DB9 connector :-) ).

I believe this is "normal" :-)

The remote machine was actually handling 8N0.. so 7N1 was treated
as 8P0 OR 8N0... The shell didn't work because it was possible to have
"mark" parity, and the parity errors would show up preventing the bytes
from being used (mark parity/or parity errors always showed up in the
most significant bit of the character). Everything looks fine, but wouldn't
work.

Setting the 8N1 forces the parity bit to zero, but including 8 data bits
and one stop bit. 7N1 is the same as 8N0, with the parity showing up as
the 8th bit. The remote (if missing a stop bit) would complete by adding
a "parity" bit...

--
-------------------------------------------------------------------------
Jesse I Pollard, II
Email: [email protected]

Any opinions expressed are solely my own.