n_tty: wake up poll(POLLRDNORM) on receiving data
commit c816b2e65b0e86b95011418cad334f0524fc33b8 upstream. The poll man page says POLLRDNORM is equivalent to POLLIN when used as an event. $ man poll <snip> POLLRDNORM Equivalent to POLLIN. However, in n_tty driver, POLLRDNORM does not return until timeout even if there is terminal input, whereas POLLIN returns. The following test program works until kernel-3.17, but the test stops in poll() after commit57087d5154
("tty: Fix spurious poll() wakeups"). [Steps to run test program] $ cc -o test-pollrdnorm test-pollrdnorm.c $ ./test-pollrdnorm foo <-- Type in something from the terminal followed by [RET]. The string should be echoed back. ------------------------< test-pollrdnorm.c >------------------------ #include <stdio.h> #include <errno.h> #include <poll.h> #include <unistd.h> void main(void) { int n; unsigned char buf[8]; struct pollfd fds[1] = {{ 0, POLLRDNORM, 0 }}; n = poll(fds, 1, -1); if (n < 0) perror("poll"); n = read(0, buf, 8); if (n < 0) perror("read"); if (n > 0) write(1, buf, n); } ------------------------------------------------------------------------ The attached patch fixes this problem. Many calls to wake_up_interruptible_poll() in the kernel source code already specify "POLLIN | POLLRDNORM". Fixes:57087d5154
("tty: Fix spurious poll() wakeups") Cc: stable@vger.kernel.org Signed-off-by: Kosuke Tatsukawa <tatsu-ab1@nec.com> Link: https://lore.kernel.org/r/TYCPR01MB81901C0F932203D30E452B3EA5209@TYCPR01MB8190.jpnprd01.prod.outlook.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
0e31f914d7
commit
d4dc28db1b
@ -1377,7 +1377,7 @@ handle_newline:
|
||||
put_tty_queue(c, ldata);
|
||||
smp_store_release(&ldata->canon_head, ldata->read_head);
|
||||
kill_fasync(&tty->fasync, SIGIO, POLL_IN);
|
||||
wake_up_interruptible_poll(&tty->read_wait, EPOLLIN);
|
||||
wake_up_interruptible_poll(&tty->read_wait, EPOLLIN | EPOLLRDNORM);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -1658,7 +1658,7 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp,
|
||||
|
||||
if (read_cnt(ldata)) {
|
||||
kill_fasync(&tty->fasync, SIGIO, POLL_IN);
|
||||
wake_up_interruptible_poll(&tty->read_wait, EPOLLIN);
|
||||
wake_up_interruptible_poll(&tty->read_wait, EPOLLIN | EPOLLRDNORM);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user