diff -up linux-4.18.0-372.26.1.el8.x86_64/fs/pipe.c,kbz216458 linux-4.18.0-372.26.1.el8.x86_64/fs/pipe.c --- linux-4.18.0-372.26.1.el8.x86_64/fs/pipe.c,kbz216458 2022-08-26 19:31:40.000000000 +0100 +++ linux-4.18.0-372.26.1.el8.x86_64/fs/pipe.c 2022-10-03 22:49:12.525329538 +0100 @@ -307,7 +307,9 @@ pipe_read(struct kiocb *iocb, struct iov if (bufs) /* More to do? */ continue; if (!pipe->writers) + { do_wakeup = 1; break; + } if (!pipe->waiting_writers) { /* syscall merging: Usually we must not sleep * if O_NONBLOCK is set, or if we got some data. @@ -328,17 +330,23 @@ pipe_read(struct kiocb *iocb, struct iov } if (do_wakeup) { wake_up_interruptible_sync_poll(&pipe->wait, EPOLLOUT | EPOLLWRNORM); - kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT); + if ( pipe->fasync_writers ) + kill_fasync(&pipe->fasync_writers, SIGIO, ( ret > 0 ) ? POLL_OUT : ((!pipe->readers) ? POLL_HUP : POLL_OUT)); } pipe_wait(pipe); } __pipe_unlock(pipe); - /* Signal writers asynchronously that there is more room. */ - if (do_wakeup) { + if ( (!pipe->writers) && pipe->fasync_readers ) + kill_fasync(&pipe->fasync_readers, SIGIO, POLL_HUP); + + if ( do_wakeup ) { + /* Signal writers asynchronously that there is more room. */ wake_up_interruptible_sync_poll(&pipe->wait, EPOLLOUT | EPOLLWRNORM); - kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT); + if ( pipe->fasync_writers ) + kill_fasync(&pipe->fasync_writers, SIGIO, (ret > 0) ? POLL_OUT : ((!pipe->readers) ? POLL_HUP : POLL_OUT)); } + if (ret > 0) file_accessed(filp); return ret; @@ -464,7 +472,8 @@ pipe_write(struct kiocb *iocb, struct io } if (do_wakeup) { wake_up_interruptible_sync_poll(&pipe->wait, EPOLLIN | EPOLLRDNORM); - kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN); + if ( pipe->fasync_readers ) + kill_fasync(&pipe->fasync_readers, SIGIO, (ret > 0) ? POLL_IN : ((!pipe->writers) ? POLL_HUP : POLL_IN)); do_wakeup = 0; } pipe->waiting_writers++; @@ -473,11 +482,14 @@ pipe_write(struct kiocb *iocb, struct io } out: __pipe_unlock(pipe); + if (do_wakeup) { wake_up_interruptible_sync_poll(&pipe->wait, EPOLLIN | EPOLLRDNORM); - kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN); + if ( pipe->fasync_readers ) + kill_fasync(&pipe->fasync_readers, SIGIO, (ret > 0) ? POLL_IN : ((!pipe->writers) ? POLL_HUP : POLL_IN)); } - if (ret > 0 && sb_start_write_trylock(file_inode(filp)->i_sb)) { + + if ((ret > 0) && sb_start_write_trylock(file_inode(filp)->i_sb)) { int err = file_update_time(filp); if (err) ret = err; @@ -569,9 +581,16 @@ pipe_release(struct inode *inode, struct if (pipe->readers || pipe->writers) { wake_up_interruptible_sync_poll(&pipe->wait, EPOLLIN | EPOLLOUT | EPOLLRDNORM | EPOLLWRNORM | EPOLLERR | EPOLLHUP); - kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN); - kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT); + if ( pipe->fasync_readers && !pipe->writers ) + kill_fasync(&pipe->fasync_readers, SIGIO, POLL_HUP); + else if (pipe->fasync_readers) + kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN); + if ( pipe->fasync_writers && !pipe->readers ) + kill_fasync(&pipe->fasync_writers, SIGIO, POLL_HUP); + else if (pipe->fasync_writers) + kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT); } + __pipe_unlock(pipe); put_pipe_info(inode, pipe);