1

In my application I am using Linux Named Pipe for a streaming data transfer. One application(app1) writes stream data to this FIFO, and other application(app2) reads from it.

When FIFO size is full, partial record will be written out to FIFO from app1, as Pipe's buffer size(4096 bytes) filled up. By this records are getting merged with some other record. So I want to know what is the remaining size in pipe buffer, before writing a record. With this I can compare current record size with remaining size in pipe buffer, If record size is more, then App1 will wait and write full complete record whenever pipe becomes free, as App2 will be reading continuously. I have tried using this, but no use:

fcntl(fd, F_GETPIPE_SZ );

Also is there a way to check this remaining pipe's buffer size using C or C++?

Nomad
  • 751
  • 4
  • 13
  • 34
  • 1
    Short answer: no there isn't. – Sam Varshavchik Dec 07 '18 at 19:08
  • I do not think it is a good design. Instead, just write whatever is writeable. Why do you want to write full message only? – SergeyA Dec 07 '18 at 19:08
  • @SergeyA: Otherwise it is dropping some records, and when ever pipe has space then it is appending other records. so it generates error records. – Nomad Dec 07 '18 at 19:11
  • 2
    Then fix your logic, so that it correctly handles the value returned from write(), and doesn't drop records. This is a very common, simple situation that's handled all the time, by correctly using what write() returns, and then making sure that the unwritten part of the previous record gets written before the next one. – Sam Varshavchik Dec 07 '18 at 19:24
  • 1
    @Dave you need to check return code from write, and if the record was not written in full, re-write the leftover. Your code will block until more space would be available. – SergeyA Dec 07 '18 at 19:26
  • @SamVarshavchik: logic change option is there, But I wanted to know If there is a way to find the left over size of buffer, so that I can check record size vs buffer free space, before writing. – Nomad Dec 07 '18 at 19:44
  • 1
    The first comment in this question already told you whether or not there is a way. That answer is still the same: no there isn't. I maintain [http://manpages.courier-mta.org](http://manpages.courier-mta.org) and I've read pretty much all Linux man pages. I do not recall anything of that sort. – Sam Varshavchik Dec 07 '18 at 20:30
  • Thanks @SamVarshavchik – Nomad Dec 07 '18 at 20:48
  • @SamVarshavchik but it is not correct. There is way, at least on some versions on Linux. I am finishing up the answer. – SergeyA Dec 07 '18 at 20:49
  • Using `FIONREAD` will not reliably work, in determining whether or not your intended write will succeed, for a number of reasons. – Sam Varshavchik Dec 07 '18 at 21:16

1 Answers1

2

While I strongly discourage this approach, there is a way of achieving desired functionality, at least on some versions of Linux . For that one need to use ioctl with FIONREAD command to get the size of unread data inside pipe. The corresponding command is not available on all Linuxes out there, but it is available on mine.

Following small snippet of code shows how this technique could be applied in practice. Please do not think much of it, it is there for illustration only.

#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>

#include <iostream>

int main() {
    const size_t buf_sz = 4096;
    int fd[2];
    pipe(fd);

    int cap = fcntl(fd[0], F_GETPIPE_SZ);
    std::cout << "Pipe capacity: " << cap << "\n";
    int sz = 0;
    while (((cap - sz) >= buf_sz)) {

        char buf[buf_sz];
        write(fd[1], buf, sizeof(buf));
        ioctl(fd[1], FIONREAD, &sz);
        std::cout << "Avaialble to write: " << cap - sz << "\n";
    }
    std::cout << "No more room in the pipe.\n";
    char buf[buf_sz];
    read(fd[0], buf, buf_sz);
    ioctl(fd[1], FIONREAD, &sz);
    std::cout << "Available now: " << cap - sz << "\n";
}

On my machine, it provides following output: saristov@saristovlinux:~$ g++ test_pipe.cpp && ./a.out

Pipe capacity: 65536
Avaialble to write: 61440
Avaialble to write: 57344
Avaialble to write: 53248
Avaialble to write: 49152
Avaialble to write: 45056
Avaialble to write: 40960
Avaialble to write: 36864
Avaialble to write: 32768
Avaialble to write: 28672
Avaialble to write: 24576
Avaialble to write: 20480
Avaialble to write: 16384
Avaialble to write: 12288
Avaialble to write: 8192
Avaialble to write: 4096
Avaialble to write: 0

No more room in the pipe.
Available now: 4096
SergeyA
  • 61,605
  • 5
  • 78
  • 137