Bug 209251 - Blocking splice() does not allow to read all the available data from pipe
Summary: Blocking splice() does not allow to read all the available data from pipe
Status: NEW
Alias: None
Product: File System
Classification: Unclassified
Component: Other (show other bugs)
Hardware: All Linux
: P1 normal
Assignee: fs_other
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-09-13 07:20 UTC by Dmitry Izbitsky
Modified: 2023-11-29 07:34 UTC (History)
3 users (show)

See Also:
Kernel Version: 5.9.0-rc4
Subsystem:
Regression: No
Bisected commit-id:


Attachments
Reproducer for the bug (6.84 KB, text/plain)
2020-09-13 07:20 UTC, Dmitry Izbitsky
Details

Description Dmitry Izbitsky 2020-09-13 07:20:42 UTC
Created attachment 292493 [details]
Reproducer for the bug

If I do the following (I checked mainline kernel 5.9.0-rc4, 4.19.0-10-amd64 on Debian, 4.15.0-106-generic on Ubuntu):

1. Overfill pipe_write_end with data;
2. Call splice(socket, 0, pipe_write_end, 0, 100, 0) from another thread which will block because there is nothing to read from the socket;
3. Try to read from pipe_read_fd all the data written in (1);

then read() will block after reading only part of the data – even though poll() reports POLLIN for pipe_read_fd. read() will block even if O_NONBLOCK is set for pipe_read_fd.

The reproducer program test_splice.c is in attachment. It can be used like

gcc test_splice.c -o test_splice -lpthread
./test_splice 127.0.0.1 11111

Output:

61441 bytes were written to pipe
Connection was accepted
Calling splice() in a thread to move data from the socket to the pipe which should block
Trying to read all the data written to pipe before

read() on pipe blocks for 4998 ms by now, after reading 4096 bytes
Sending data from peer to unblock splice()
splice() returned 10
61451 bytes was read from pipe
Joining a thread which calls splice()...
Joining a thread which unblocks splice()...


If I run this program on 3.10.0-1062.1.2.el7.x86_64 (CentOS Linux release 7.7.1908), it works fine:

./test_splice 127.0.0.1 11111
61441 bytes were written to pipe
Connection was accepted
Calling splice() in a thread to move data from the socket to the pipe which should block
Trying to read all the data written to pipe before
61441 bytes was read from pipe
Joining a thread which calls splice()...
Sending data from peer to unblock splice()
splice() returned 10
Joining a thread which unblocks splice()...

Note You need to log in before you can comment on or make changes to this bug.