Home > Blockchain >  fgets not able to read from pipe twice on Ubuntu 20.04
fgets not able to read from pipe twice on Ubuntu 20.04

Time:10-22

I have the following code that used to work on Ubuntu 18.04. Now, I compiled and run it in Ubuntu 20.04, and, for some reason, the code stop working.

The code is meant to read from a named pipe. To test it, I create the pipe with mkfifo /tmp/pipe and then I write into the pipe with echo "message" >> /tmp/pipe.

The first time the fgets() method is executed, the function returns the expected value from the pipe; but from the second invocation on, the method returns NULL and the code gets stuck on the loop even when I execute several echo commands.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vector>
#include <sstream>
#include <fstream>
#include <limits>
#include <iomanip>

#include <iostream>
#include <cstdlib>

using namespace std;

FILE* result_pipe_stream;

string read_result_from_pipe(){
    if (result_pipe_stream == NULL){
        printf("\n[BINDING-COMMONS] ERROR: Pipe is not set");
        return NULL;
    }
    
    
    std::stringstream oss;
    while (1) {
        char buf[BUFSIZ];
        if( fgets (buf, BUFSIZ, result_pipe_stream) != NULL ) {
            int buflen = strlen(buf);
            if (buflen >0){
                if (buf[buflen-1] == '\n'){
                        buf[buflen-1] = '\0';
                        oss << buf;
                        return oss.str();
                } else {
                    oss << buf;
                    // line was truncated. Read another block to complete line.
                }
            }
        }
    }   
}

int main(int argc, char *argv[]){
    result_pipe_stream = fopen("/tmp/pipe" , "r");
    while (1){
        cout << read_result_from_pipe() << '\n';
    }
}

  1. Why is the code not working anymore? I assume that some library has changed in the distribution and fgets is no longer able to read properly from the pipe
  2. How can I workaround that problem?

CodePudding user response:

if( fgets (buf, BUFSIZ, result_pipe_stream) != NULL ) --> Once fgets() returns NULL due to end-of-file, it will continue to return NULL on subsequent calls without reading unless the end-of-file indicator for result_pipe_stream is cleared - like with clearerr(). Codes gets stuck in an infinite loop, never reading anymore and it should.

The real question is why it "worked" in Ubuntu 18.04. I suspect that version was not compliant.

while (1) {
    char buf[BUFSIZ];
    if( fgets (buf, BUFSIZ, result_pipe_stream) != NULL ) {
      ...
    }
     // Perhaps assess why here, end-of-file, input error, too often here, ...
    clearerr(result_pipe_stream); // add
}
  • Related