boostorg / boostorg/process

Setting the capacity of the underline pipe. Linux only

Open
#322 4 comments 0 reactions 0 assignees View on GitHub
Dominant language
C++
Stars
145
Forks
151
PR merge metrics
No merged PRs in 30d

Description

I work for a big security vendor, and recently we tried to shift from libc interface (fork, exec, waitpid...) to Boost::Process.
However, we are missing some crucial API's related to the underline pipe.
One of the functionality we need is: Setting the pipe capacity.
If the pipe fills up, 2 things may happen (Depends if the pipe is nonblocking or blocking):
1) **The producer will be blocked**. From [pipe man page](https://man7.org/linux/man-pages/man7/pipe.7.html): "If a process attempts to write to a full pipe, then blocks until sufficient data has been read from the pipe to allow the write to complete"
2) **The new data will be thrown**. From [pipe man page](https://man7.org/linux/man-pages/man7/pipe.7.html): "If the pipe is full, then write(2) fails, with errno set to EAGAIN."

Both cases cause us to loose live data from the producer.
increasing the pipe capacity doesn't solve this issue 100%. But the possibility of this happening, diminishing by a lot.
This is crucial for us.

**Running the following code for 5 seconds:**
```
int main()
{
bp::ipstream stdOut;
bp::child childProcess = bp::child("sysdig", bp::std_out > stdOut);
auto fdStdOut = stdOut.pipe().native_source();

while (true)
{
int bytesInPipe;
ioctl(fdStdOut, FIONREAD, &bytesInPipe); // Find number of available bytes
std::string output(bytesInPipe + 1, 0);
std::cout << "\nPipe size: " << fcntl(fdStdOut, F_GETPIPE_SZ) << std::endl;
std::cout << "Bytes available: " << bytesInPipe << std::endl;
std::cout << "Bytes read: " << read(fdStdOut, output.data(), bytesInPipe) << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(50)); // Some work
}
}
```

**Here is some of the output**:
```
Pipe size: 65536
Bytes available: 17685
Bytes read: 17685

Pipe size: 65536
Bytes available: 5577
Bytes read: 5577

Pipe size: 65536
Bytes available: 65536
Bytes read: 65536

Pipe size: 65536
Bytes available: 65421
Bytes read: 65421

Pipe size: 65536
Bytes available: 4564
Bytes read: 4564
```
The capacity is easily reached.

After changing the pipe capacity to the value specified at: /proc/sys/fs/pipe-max-size, I was able to 20X the pipe capacity.
**New code**
```
int main()
{
bp::ipstream stdOut;
bp::child childProcess = bp::child("sysdig", bp::std_out > stdOut);
auto fdStdOut = stdOut.pipe().native_source();
std::cout << "new pipe capacity: " << fcntl(fdStdOut, F_SETPIPE_SZ, 1048576) << std::endl; // Changing the capacity

while (true)
{
int bytesInPipe;
ioctl(fdStdOut, FIONREAD, &bytesInPipe); // Find number of available bytes
std::string output(bytesInPipe + 1, 0);
std::cout << "\nPipe size: " << fcntl(fdStdOut, F_GETPIPE_SZ) << std::endl;
std::cout << "Bytes available: " << bytesInPipe << std::endl;
std::cout << "Bytes read: " << read(fdStdOut, output.data(), bytesInPipe) << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(50)); // Some work
}
}
```
New output:
```
new pipe capacity: 1048576

Pipe size: 1048576
Bytes available: 259710
Bytes read: 259710
```

I have created a Pull request that will add this functionality, without the the user accessing the file descriptor or calling fcntl()
PR: https://github.com/boostorg/process/pull/324

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.