[PATCH 0/0] SIGWINCH problem with terminal apps

From: Adam TlaÅka
Date: Mon Oct 06 2008 - 08:14:32 EST


Welcome,

I've observed then very often a X11 terminal app is not getting proper
window sizes afer terminal resize operation. This could be seen with
mc, jed, vim or other curses and not curses aware apps.

I wrote a simple program which just does nothing but uses SIGWINCH
handler so I can observe values reported by ioctl(1,TIOCGWINS,&ws) call
inside my signal handler. What is interesting that from time to time it
obtain unchanged values. It means values which were valid just before
terminal resize.

In drivers/char/vt.c and drivers/char/tty_io.c variables
vc->vc_tty->winsize and tty->winsize , real_tty->winsize are updated
after kill_pgrp(pgrp, SIGWINCH, 1) calls. I am not very familiar with
mutex design and how it corresponds to kill_pgrp() kernel function but
it seems that locking is not working here as we expect. An app can read
tty winsize data through ioctl() call in SIGWINCH handler and obtain
uchanged values.

So as a quick solution I made patches which move mentioned updates
before kill_pgrp() calls. As I tested modified kernel there is no
observed effect now. So I send patchs.

There are some places where kill_pgrp() call is used and some variable
is changed after it. It should be considered if this code is always
working properly or some race scheduler condition exists.

Signed-off-by: Adam Tla/lka <atlka@xxxxxxxxx>

--
Adam TlaÅka mailto:atlka@xxxxxxxxx ^v^ ^v^ ^v^
System & Network Administration Group - - - ~~~~~~
Computer Center, GdaÅsk University of Technology, Poland
--- drivers/char/tty_io_orig.c 2008-10-06 11:03:39.000000000 +0200
+++ drivers/char/tty_io.c 2008-10-06 11:20:54.000000000 +0200
@@ -3021,6 +3021,9 @@ static int tiocswinsz(struct tty_struct
rpgrp = get_pid(real_tty->pgrp);
spin_unlock_irqrestore(&tty->ctrl_lock, flags);

+ tty->winsize = tmp_ws;
+ real_tty->winsize = tmp_ws;
+
if (pgrp)
kill_pgrp(pgrp, SIGWINCH, 1);
if (rpgrp != pgrp && rpgrp)
@@ -3028,9 +3031,6 @@ static int tiocswinsz(struct tty_struct

put_pid(pgrp);
put_pid(rpgrp);
-
- tty->winsize = tmp_ws;
- real_tty->winsize = tmp_ws;
done:
mutex_unlock(&tty->termios_mutex);
return 0;
--- drivers/char/vt_orig.c 2008-10-06 11:01:26.000000000 +0200
+++ drivers/char/vt.c 2008-10-06 11:59:48.000000000 +0200
@@ -921,11 +921,11 @@ int vc_resize(struct vc_data *vc, unsign
if ((ws.ws_row != cws->ws_row || ws.ws_col != cws->ws_col))
pgrp = get_pid(vc->vc_tty->pgrp);
spin_unlock_irq(&vc->vc_tty->ctrl_lock);
+ *cws = ws;
if (pgrp) {
kill_pgrp(vc->vc_tty->pgrp, SIGWINCH, 1);
put_pid(pgrp);
}
- *cws = ws;
mutex_unlock(&vc->vc_tty->termios_mutex);
}