Commit 28e58ee8ce1f0e69c207f747b7b9054b071e328d

Authored by Linus Torvalds
1 parent d7b9935a34

Fix broken "pipe: use event aware wakeups" optimization

Commit e462c448fdc8 ("pipe: use event aware wakeups") optimized the pipe
event wakeup calls to avoid wakeups if the events do not match the
requested set.

However, the optimization was buggy, in that it didn't actually use the
correct sets for the events: when we make room for more data to be
written, the pipe poll() routine will return both the POLLOUT _and_
POLLWRNORM bits.  Similarly for read.

And most critically, when a pipe is released, that will potentially
result in POLLHUP|POLLERR (depending on whether it was the last reader
or writer), not just the regular POLLIN|POLLOUT.

This bug showed itself as a hung gnome-screensaver-dialog process, stuck
forever (or at least until it was poked by a signal or by being traced)
in a poll() system call.

Cc: Davide Libenzi <davidel@xmailserver.org>
Cc: David S. Miller <davem@davemloft.net>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 1 changed file with 5 additions and 5 deletions Side-by-side Diff

... ... @@ -441,7 +441,7 @@
441 441 break;
442 442 }
443 443 if (do_wakeup) {
444   - wake_up_interruptible_sync_poll(&pipe->wait, POLLOUT);
  444 + wake_up_interruptible_sync_poll(&pipe->wait, POLLOUT | POLLWRNORM);
445 445 kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
446 446 }
447 447 pipe_wait(pipe);
... ... @@ -450,7 +450,7 @@
450 450  
451 451 /* Signal writers asynchronously that there is more room. */
452 452 if (do_wakeup) {
453   - wake_up_interruptible_sync_poll(&pipe->wait, POLLOUT);
  453 + wake_up_interruptible_sync_poll(&pipe->wait, POLLOUT | POLLWRNORM);
454 454 kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
455 455 }
456 456 if (ret > 0)
... ... @@ -612,7 +612,7 @@
612 612 break;
613 613 }
614 614 if (do_wakeup) {
615   - wake_up_interruptible_sync_poll(&pipe->wait, POLLIN);
  615 + wake_up_interruptible_sync_poll(&pipe->wait, POLLIN | POLLRDNORM);
616 616 kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
617 617 do_wakeup = 0;
618 618 }
... ... @@ -623,7 +623,7 @@
623 623 out:
624 624 mutex_unlock(&inode->i_mutex);
625 625 if (do_wakeup) {
626   - wake_up_interruptible_sync_poll(&pipe->wait, POLLIN);
  626 + wake_up_interruptible_sync_poll(&pipe->wait, POLLIN | POLLRDNORM);
627 627 kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
628 628 }
629 629 if (ret > 0)
... ... @@ -715,7 +715,7 @@
715 715 if (!pipe->readers && !pipe->writers) {
716 716 free_pipe_info(inode);
717 717 } else {
718   - wake_up_interruptible_sync_poll(&pipe->wait, POLLIN | POLLOUT);
  718 + wake_up_interruptible_sync_poll(&pipe->wait, POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM | POLLERR | POLLHUP);
719 719 kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
720 720 kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
721 721 }