0

I'm coding an application on a Raspberry Pi/Raspbian in C++. I create a named pipe (FIFO) with mkfifo() then I start raspiyuv to grab image from my camera. For memory, raspiyuv is the Raspberry Pi command line application that takes still images and save them as YUV file.

I'm using g++ 6.3 and Boost 1.64 with -std=c++17. The FIFO I create is correct in the sense that I can use it from command line. It works as expected.

The bug is that the application raspiyuv I spawn returns immediately with exit code 0.

My code:

void myFunction()
{
    // Create the FIFO here with mkfifo(); // Works fine...
    boost::filesystem::path lExecPath = 
        boost::process::search_path( "raspiyuv" );  // returns correct path
    boost::process::child lProcess( lExecPath, "-w 2592 -h 1944 -o - -t 0 -y -s >> /var/tmp/myfifo" );
    int lPID = lProcess.id();   // Seems to be correct
    int lExitCode = lProcess.exit_code();  // Returns immediately with 0
}

The command $ raspiyuv -w 2592 -h 1944 -o - -t 0 -y -s is correct when I enter it directly to the command line. Also, the redirection to the FIFO works correctly. -w 2592 -h 1944 give the size of the grabbed image, -o - means output image to stdout, -t 0 means wait forever, -y means save only the Y channel and -s means wait for SIGUSR1 to trigger image capture.

When I call it from the command line, the application is idle until I send a SIGUSR1 then it captures an image and streams it to the FIFO then returns idle. That's fine.

When I spawn it by creating the boost::process::child object, it returns immediately.

Any idea to correct this and allow the boost::process::child to remain alive as long as my application (parent process) is alive and I don't send a SIGKILL, etc.?

Thanks for your help!

dom_beau
  • 2,437
  • 3
  • 30
  • 59

1 Answers1

0

The boost::process::childruns asyncronously to main process. If you want synchronous behavior then you must either call lProcess.wait() or launch that raspiyuv by synchronous means like using boost::process::system.

EDIT: If you want the other process to be asynchronous (as your edits and comment seem to indicate) then what you really try to do becomes unclear to me:

The bug is that the application raspiyuv I spawn returns immediately with exit code 0.

What bug? By docs of boost::process::child it is exactly what is expected:

  1. int exit_code() const; Get the exit_code. The return value is without any meaning if the child wasn't waited for or if it was terminated.

Your code nowhere waits for child to end and so gets exit code like documented.

Öö Tiib
  • 10,809
  • 25
  • 44
  • Actually, I do want it to run _asynchronously_. I will sporadically synchronize it by sending a __SIGUSR1__ signal to the child process. What I want is a child process that runs asynchronously like a thread (but being a different process). Any way... I'll try `boost::process::system` when I will have access to my computer. – dom_beau Oct 11 '17 at 14:07
  • I extended my answer since I really do not understand what is the issue if you expected the child process to be asynchronous. – Öö Tiib Oct 11 '17 at 16:58
  • The problem is that launching `raspiyuv ... -t 0 -s ...` should start the app in a (forever) idle state waiting for SIGUSR1 to trig actual image capture _then go back to idle state waiting for next SIGUSR1_. It should not return immediately with code 0. – dom_beau Oct 11 '17 at 19:23
  • No, the problem is that your posted code does not wait for what you attempt to execute to complete so it can't detect what the exit code of it is. – Öö Tiib Oct 11 '17 at 20:08
  • No the program returns immediatelly. When I run it with the debugger, it even returns and its PID disappears when I do `ps aux`. It should not. – dom_beau Oct 11 '17 at 22:05
  • I did nowhere write how soon it returns. I wrote that your code does not wait for exit code. – Öö Tiib Oct 12 '17 at 06:18