Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

splice: reinstate SIGPIPE/EPIPE handling

Commit 8924feff66f3 ("splice: lift pipe_lock out of splice_to_pipe()")
caused a regression when there were no more readers left on a pipe that
was being spliced into: rather than the expected SIGPIPE and -EPIPE
return value, the writer would end up waiting forever for space to free
up (which obviously was not going to happen with no readers around).

Fixes: 8924feff66f3 ("splice: lift pipe_lock out of splice_to_pipe()")
Reported-and-tested-by: Andreas Schwab <schwab@linux-m68k.org>
Debugged-by: Al Viro <viro@zeniv.linux.org.uk>
Cc: stable@kernel.org # v4.9
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

+7 -2
+7 -2
fs/splice.c
··· 1087 1087 1088 1088 static int wait_for_space(struct pipe_inode_info *pipe, unsigned flags) 1089 1089 { 1090 - while (pipe->nrbufs == pipe->buffers) { 1090 + for (;;) { 1091 + if (unlikely(!pipe->readers)) { 1092 + send_sig(SIGPIPE, current, 0); 1093 + return -EPIPE; 1094 + } 1095 + if (pipe->nrbufs != pipe->buffers) 1096 + return 0; 1091 1097 if (flags & SPLICE_F_NONBLOCK) 1092 1098 return -EAGAIN; 1093 1099 if (signal_pending(current)) ··· 1102 1096 pipe_wait(pipe); 1103 1097 pipe->waiting_writers--; 1104 1098 } 1105 - return 0; 1106 1099 } 1107 1100 1108 1101 static int splice_pipe_to_pipe(struct pipe_inode_info *ipipe,