n_tty: wake up poll(POLLRDNORM) on receiving data
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 commit 57087d5154 ("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:
committed by
Greg Kroah-Hartman
parent
26291c54e1
commit
c816b2e65b
@@ -1329,7 +1329,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;
|
||||
}
|
||||
}
|
||||
@@ -1561,7 +1561,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user