summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormillert <millert@openbsd.org>2013-10-11 12:44:12 +0000
committermillert <millert@openbsd.org>2013-10-11 12:44:12 +0000
commitc550da31e2154b46bf0a9f337ccc635a1e743971 (patch)
tree8006ad469a756a598a9cb46a12decf81936b65c4
parentPrevent non-data packets from being dropped. (diff)
downloadwireguard-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.c7
-rw-r--r--sys/kern/tty_pty.c12
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) ||