3

I am using Boost Process in async mode to get the stdout, stderr and return code of a shell command. In the code snippet below, is the call c.wait() required? According to Boost Process 1.68 documentation it is not required where as it is required according to that of boost process 1.65.1.

std::string command = "ls";
boost::asio::io_service ios;
std::future<std::string> dataOut;
std::future<std::string> dataErr;
bp::child c(command, bp::std_in.close(), bp::std_out > dataOut, bp::std_err > dataErr, ios);
ios.run();
c.wait();
stdOut = dataOut.get();
stdErr = dataErr.get();
returnStatus = c.exit_code();

Now, I am using Boost 1.68 and when I remove the call to c.wait(), I get a returnStatus of 127 instead of the expected 0, which I get when I add the c.wait() call. What difference does the call c.wait() make?

bisarch
  • 1,388
  • 15
  • 31
  • 2
    The note about `wait()` not being necessary seems to conflict with the class documentation. https://www.boost.org/doc/libs/1_68_0/doc/html/boost/process/child.html#idp44365552-bb I think the docs need some more work. – Richard Hodges Oct 01 '18 at 10:41
  • @RichardHodges, doesn't ios.run() wait for the process to exit? If yes, then why is c.wait() needed? – bisarch Oct 01 '18 at 10:53
  • 1
    You would think that internally `waitpid()` has been called (perhaps even on a second service thread) but I have not spent time looking at the source code to check. Why not write a little MCVE to prove the documentation wrong and raise it as a bug? – Richard Hodges Oct 01 '18 at 11:03

1 Answers1

1

Yes, run() normally waits for async operations to complete.

However, you could have an alternative termination of run()

  • when an exception emanates from a handler
  • when another thread calls stop()
  • when async signals alter program flow

In such cases it would be advisable to still use wait() so you avoid zombies. Other than that, the on_exit() handler is the more flexible approach, in that it will allow you to multiplex several processes on the same io_context/io_service instance and still respond to child process completion as soon as possible.

sehe
  • 374,641
  • 47
  • 450
  • 633
  • 1
    I ran the above program many times on my Centos7 machine with and without the c.wait() call. In every single case, simple commands like 'ls', 'pwd', 'uname' have a c.exit_code() value of 127 without the c.wait() call, whereas it changes to 0 with a c.wait() call. So, it doesn't seem like normally run() waits for sync operations to complete. – bisarch Oct 03 '18 at 10:01