0

I am trying to parse a stream by using popen with a command that returns a constant stream of output lines.

This makes the application to get stuck on the fgets() call.

Here's the method:

std::string MyClass::InvokeCmd(std::string command)
{
    std::string result;
    std::array<char, 128> buffer;
    FILE *pipe = popen(command.c_str(), "r");

        while (fgets(buffer.data(), 128, pipe) != NULL)
        {
            result += buffer.data();
        }
    }
    pclose(pipe);
    return result;
}

The command is a ROS command:

rostopic hz /topicname

The command runs continuously and produces one line of output approximately every second.

If I wait for around 30 sec (looks like flush time of a buffer) I do see the data.

Gil404
  • 711
  • 1
  • 8
  • 22
  • Your code does not show the actual command. Is it real code? –  May 22 '18 at 19:27
  • Hi @Arkadiy, looks like it is getting stuck on the while. However I noticed that if I wait for around 30 sec (looks like flush time of a buffer) I do see the data. The command is rostopic hz /topicname – Gil404 May 22 '18 at 19:32
  • Does the command produce output immediately if it's run in command line? –  May 22 '18 at 19:57
  • Yes, it prints a line every second. – Gil404 May 22 '18 at 20:03
  • Correct. I am getting the same latency with the cat piped to it. Is there anyhing that can done? – Gil404 May 22 '18 at 20:29

2 Answers2

1

This looks like buffering inside the rostopic utility. When stdout goes to a terminal, many C libraries are smart enough to flush every time '\n' is written. When stdout goes to a pipe, the library would add a large buffer. Looks like it takes 30 seconds to fill it.

To test this theory, try rostopic hz /topicname | cat in command line.

There is not much that can be done, please see this question.

-1

I suggest you pit some asserting that pipe is not nullptr. If it is nullptr, then perhaps print out command, errno and strerror().

Gem Taylor
  • 5,381
  • 1
  • 9
  • 27