mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Ensure EOF is handled propertly during splice.
PiperOrigin-RevId: 304684417
This commit is contained in:
committed by
gVisor bot
parent
4032cf06e4
commit
a94309628e
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user