c++ - How to reproduce deadlock hinted to by Boost process documentation? -


according boost documentation (section 'why pipe not close?'), following code result in deadlock:

#include <boost/process.hpp>  #include <iostream>  namespace bp = ::boost::process;  int main(void) {   bp::ipstream is;   bp::child c("ls", bp::std_out > is);    std::string line;   while (std::getline(is, line))   {     std::cout << line << "\n";   }    return 0; } 

the documentation says:

this deadlock, because pipe not close when subprocess exits. ipstream still data though process has ended.

however, not able reproduce deadlock (under linux). furthermore, not understand why deadlock occur in first place. once child process exits closes write-end of pipe. read-end of pipe still available parent process read from, , std::getline() fail once no more data available in pipe buffer, , write-end closed, correct? in case pipe buffer fills during execution of child process, child process block waiting parent process read enough data pipe can continue.

so in case above code can deadlock, there easy way reproduce deadlock scenario?

update:

indeed, following piece of code deadlocks using boost process:

#include <boost/process.hpp> #include <iostream>  namespace bp = ::boost::process;  int main()  {     bp::ipstream is;     bp::child c("/bin/bash", bp::args({"-c", "ls >&40"}), bp::posix::fd.bind(40, is.rdbuf()->pipe().native_sink()));      std::string line;     while (std::getline(is, line))     {         std::cout << line << "\n";     }      c.wait();      return 0; } 

i wonder whether unavoidable property of process spawning under linux though. reproducing above example using subprocess facebook's folly library @ least not deadlock:

#include <folly/subprocess.h> #include <iostream>  int main() {    std::vector<std::string> arguments = {"/bin/bash", "-c", "ls >&40"};     folly::subprocess::options options;    options.fd(40, stdout_fileno);     folly::subprocess p(arguments, options);    std::cout << p.communicate().first;    p.wait();     return 0; } 

once child process exits closes write-end of pipe.

this seems assumption. program closes pipe?

if /bin/ls does, happens for

bp::child c("/bin/bash", bp::args({"-c", "ls; ls"})); 

if ls close it, should closed twice.

perhaps bash duplicates handles under hood, subprocesses close different copies of same pipe. i'm not sure reliability of these semantics¹

so, apparently stdout well-catered for. however, can reproduce deadlock when using non-standard file-descriptor output on linux:

#include <boost/process.hpp> #include <iostream>  namespace bp = ::boost::process;  int main() {     bp::ipstream is;     bp::child c("/bin/bash", bp::args({"-c", "exec >&40; ls"}), bp::posix::fd.bind(40, is.rdbuf()->pipe().native_sink()));      std::string line;     while (std::getline(is, line)) {         std::cout << line << "\n";     } } 

i'm not sure why "closing stdout" behaviour of sub processes in bash should behave differently when redirected fd, there go.

another nice way demonstrate related deadlock is:

{     bp::child c("/bin/bash", bp::args({"-c", "ls -r /"}), bp::std_out > is);     c.wait();     return c.exit_code(); } 

this answer not conclusive observe points , demonstrate them on linux:

  • not filedescriptors seem covered same stdout
  • deadlocks can occur in many scenarios subprocesses handles io asynchronously calling process treats them synchronously.

i think latter point in documentation.


¹ indeed documentation explicitly suggests difference in these semantics problem in win32:

it not possible use automatically pipe-closing in library, because pipe might file-handle (as async pipes on windows)


Comments

Popular posts from this blog

python - Operations inside variables -

Generic Map Parameter java -

arrays - What causes a java.lang.ArrayIndexOutOfBoundsException and how do I prevent it? -