Ensure EOF is handled propertly during splice.

PiperOrigin-RevId: 304684417
This commit is contained in:
Adin Scannell
2020-04-03 13:40:51 -07:00
committed by gVisor bot
parent 4032cf06e4
commit a94309628e
2 changed files with 38 additions and 3 deletions
+10 -3
View File
@@ -255,7 +255,8 @@ func (p *Pipe) write(ctx context.Context, ops writeOps) (int64, error) {
// POSIX requires that a write smaller than atomicIOBytes (PIPE_BUF) be
// atomic, but requires no atomicity for writes larger than this.
wanted := ops.left()
if avail := p.max - p.view.Size(); wanted > avail {
avail := p.max - p.view.Size()
if wanted > avail {
if wanted <= p.atomicIOBytes {
return 0, syserror.ErrWouldBlock
}
@@ -268,8 +269,14 @@ func (p *Pipe) write(ctx context.Context, ops writeOps) (int64, error) {
return done, err
}
if wanted > done {
// Partial write due to full pipe.
if done < avail {
// Non-failure, but short write.
return done, nil
}
if done < wanted {
// Partial write due to full pipe. Note that this could also be
// the short write case above, we would expect a second call
// and the write to return zero bytes in this case.
return done, syserror.ErrWouldBlock
}
+28
View File
@@ -530,6 +530,34 @@ TEST(SendFileTest, SendToSpecialFile) {
SyscallSucceedsWithValue(kSize & (~7)));
}
TEST(SendFileTest, SendFileToPipe) {
// Create temp file.
constexpr char kData[] = "<insert-quote-here>";
constexpr int kDataSize = sizeof(kData) - 1;
const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith(
GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode));
const FileDescriptor inf =
ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY));
// Create a pipe for sending to a pipe.
int fds[2];
ASSERT_THAT(pipe(fds), SyscallSucceeds());
const FileDescriptor rfd(fds[0]);
const FileDescriptor wfd(fds[1]);
// Expect to read up to the given size.
std::vector<char> buf(kDataSize);
ScopedThread t([&]() {
absl::SleepFor(absl::Milliseconds(100));
ASSERT_THAT(read(rfd.get(), buf.data(), buf.size()),
SyscallSucceedsWithValue(kDataSize));
});
// Send with twice the size of the file, which should hit EOF.
EXPECT_THAT(sendfile(wfd.get(), inf.get(), nullptr, kDataSize * 2),
SyscallSucceedsWithValue(kDataSize));
}
} // namespace
} // namespace testing