2

There are tons of questions about non blocking pipes, but there are NO examples of code that can be copy&paste (with little correction) and used.

I got the idea and sources from this thread: Non-blocking pipe using popen?

But how to use it? At while cycle? Please, review my changes. Is it really need to use errno == EAGAIN & additional header #include <cerrno> ? Suggest you own better version if need:

    FILE *pipe;
    char buff[512];
    if ( !(pipe = popen( command.c_str(), "r")) ) return false;

    int d = fileno(pipe);   
    while ( true )
    {
        ssize_t r = read(d, buff, sizeof(buff));
        if (r == -1 && errno == EAGAIN) // really need errno? 
            continue;
        else if (r > 0)
            ptr_output->append(buff);       
        else
            break;
    }

    pclose(pipe);
Community
  • 1
  • 1
abrahab
  • 2,430
  • 9
  • 39
  • 64
  • 2
    The pipe isn't non-blocking, you failed to copy'n'paste the right code. – Jonathan Wakely Jun 09 '12 at 20:19
  • @JonathanWakely !!! you are amazing! only you found that its blocking! I does not sleep 24h and trying to solve the problem and lose one sting, and ofcouce its does not help. maybe now my threads will not slow down. thnaks. – abrahab Jun 09 '12 at 22:01
  • You should not edit the question away like that to support [a follow on questions](http://stackoverflow.com/q/10984490/2509). It leaves this question looking nonsensical. Reproduce the code in the new question instead. – dmckee --- ex-moderator kitten Jun 11 '12 at 17:53

2 Answers2

1

Yes. If the read call returns with the error value (-1) and errno is set to EAGAIN, that means that no data is available, so you continue the loop to try again. If you got rid of the errno, errors would be effectively ignored, and your program would probably crash. Imagine if you did remove it: When read returned -1, but, say, the error was that the pipe was broken (the other end closed it), you would just keep trying to loop and enter an infinite loop. Bad idea.

Linuxios
  • 34,849
  • 13
  • 91
  • 116
0

In my Linux multithreaded application (Ubuntu 16.04, x86_64, Native POSIX Threads, libc.so.6 version Ubuntu GLIBC 2.23-0ubuntu9) this code

int fd = fileno(pipe);
fcntl(fd, F_SETFL, O_NONBLOCK);
while (true)
        {
            ssize_t r = read(fd, buff, sizeof(buff));
            if ((r == -1) && (errno == EAGAIN)) // really need errno?
                continue;
            else
            {
                if (r > 0)
                    result += buff;
                else
                    break;
            }
        }

even with fctnl(...) causes fail as not only output of command but many another arbitrary values from RAM are often read. I think it is due to thread unsafety of the code.

(Example: execute echo 3 values, 10, 30, and 40, in parallel by 20 threads, read the values and display only the last value. Output: 40 QIh MIh 40 40 30...)

Another code from this answer works fine due to fgets implementation is thread-safe:

while (!feof(pipe))
{
    if (fgets(buff, sizeof(buff), pipe) != NULL)
    result += buff;
}
John_West
  • 2,239
  • 4
  • 24
  • 44