diff options
author | 2013-10-11 12:44:12 +0000 | |
---|---|---|
committer | 2013-10-11 12:44:12 +0000 | |
commit | c550da31e2154b46bf0a9f337ccc635a1e743971 (patch) | |
tree | 8006ad469a756a598a9cb46a12decf81936b65c4 | |
parent | Prevent non-data packets from being dropped. (diff) | |
download | wireguard-openbsd-c550da31e2154b46bf0a9f337ccc635a1e743971.tar.xz wireguard-openbsd-c550da31e2154b46bf0a9f337ccc635a1e743971.zip |
poll(2) on a closed tty should return POLLIN|POLLHUP in revents
when events is set to POLLIN and POLLHUP when events is set to
POLLOUT. In the pty case we need to be careful to only treat the
pty as closed if carrier is on. This fixes a hang on close problem
seen with ssh and xterm.
-rw-r--r-- | sys/kern/tty.c | 7 | ||||
-rw-r--r-- | sys/kern/tty_pty.c | 12 |
2 files changed, 11 insertions, 8 deletions
diff --git a/sys/kern/tty.c b/sys/kern/tty.c index fa82a3db1ca..8248643322b 100644 --- a/sys/kern/tty.c +++ b/sys/kern/tty.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tty.c,v 1.101 2013/10/06 01:10:53 millert Exp $ */ +/* $OpenBSD: tty.c,v 1.102 2013/10/11 12:44:12 millert Exp $ */ /* $NetBSD: tty.c,v 1.68.4.2 1996/06/06 16:04:52 thorpej Exp $ */ /*- @@ -1065,7 +1065,10 @@ ttpoll(dev_t device, int events, struct proc *p) !ISSET(tp->t_state, TS_CARR_ON))) revents |= events & (POLLIN | POLLRDNORM); } - if (events & (POLLOUT | POLLWRNORM)) { + /* NOTE: POLLHUP and POLLOUT/POLLWRNORM are mutually exclusive */ + if (!ISSET(tp->t_cflag, CLOCAL) && !ISSET(tp->t_state, TS_CARR_ON)) { + revents |= POLLHUP; + } else if (events & (POLLOUT | POLLWRNORM)) { if (tp->t_outq.c_cc <= tp->t_lowat) revents |= events & (POLLOUT | POLLWRNORM); } diff --git a/sys/kern/tty_pty.c b/sys/kern/tty_pty.c index ba902675545..1346ef36971 100644 --- a/sys/kern/tty_pty.c +++ b/sys/kern/tty_pty.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tty_pty.c,v 1.61 2013/10/06 01:10:53 millert Exp $ */ +/* $OpenBSD: tty_pty.c,v 1.62 2013/10/11 12:44:13 millert Exp $ */ /* $NetBSD: tty_pty.c,v 1.33.4.1 1996/06/02 09:08:11 mrg Exp $ */ /* @@ -615,10 +615,7 @@ ptcpoll(dev_t dev, int events, struct proc *p) struct tty *tp = pti->pt_tty; int revents = 0, s; - if (!ISSET(tp->t_state, TS_CARR_ON)) - return (POLLHUP); - - if (!ISSET(tp->t_state, TS_ISOPEN)) + if (!ISSET(tp->t_state, TS_ISOPEN) && ISSET(tp->t_state, TS_CARR_ON)) goto notopen; if (events & (POLLIN | POLLRDNORM)) { @@ -632,7 +629,10 @@ ptcpoll(dev_t dev, int events, struct proc *p) revents |= events & (POLLIN | POLLRDNORM); splx(s); } - if (events & (POLLOUT | POLLWRNORM)) { + /* NOTE: POLLHUP and POLLOUT/POLLWRNORM are mutually exclusive */ + if (!ISSET(tp->t_state, TS_CARR_ON)) { + revents |= POLLHUP; + } else if (events & (POLLOUT | POLLWRNORM)) { if ((pti->pt_flags & PF_REMOTE) ? (tp->t_canq.c_cc == 0) : ((tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG(tp) - 2) || |