In the following code, I am trying to implement a program that runs a shell command and get the stdio
, stderr
and return code. I am doing it using boost process
in the async
mode as advised here.
namespace bp = boost::process;
class Process {
public:
Process(std::string & cmd, const int timeout);
void run();
private:
void timeout_handler();
const std::string command;
const int timeout;
bool killed;
bool stopped;
std::string stdOut;
std::string stdErr;
int returnStatus;
boost::asio::io_service ios;
boost::process::group group;
boost::asio::deadline_timer deadline_timer;
};
Process::Process(std::string & cmd, const int timeout):
command(cmd),
timeout(timeout),
deadline_timer(ios)
{}
void Process::timeout_handler()
{
if (stopped)
return;
if (deadline_timer.expires_at() <= boost::asio::deadline_timer::traits_type::now())
{
std::cout << "Time Up!" << std::endl;
group.terminate();
std::cout << "Killed the process and all its decendents" << std::endl;
killed = true;
stopped = true;
deadline_timer.expires_at(boost::posix_time::pos_infin);
}
deadline_timer.async_wait(std::bind(&Process::timeout_handler, this));
}
void Process::run()
{
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, group);
deadline_timer.expires_from_now(boost::posix_time::seconds(timeout));
deadline_timer.async_wait(std::bind(&Process::timeout_handler, this));
ios.run();
c.wait();
stdOut = dataOut.get();
stdErr = dataErr.get();
returnStatus = c.exit_code();
}
int main(int argc, char** argv)
{
if(argc < 2)
{
std::cout << "Usage: \na.out <command>" << std::endl;
exit(1);
}
std::vector<std::string> arguments(argv + 1, argv + argc);
std::string command;
for( const auto & tok : arguments)
{
command += tok + " ";
}
std::cout << command << std::endl;
Process p(command, 10);
p.run();
return 0;
}
Now, the above code returns only after deadline_timer
expires. What I want is that the child process should exit if it finishes before the timer expires or it (along with all the child processes it forks), should be terminated. Please point out the mistake in my code.
"echo hello"
will do something else than "echo" "hello"`). See also boost.org/doc/libs/1_68_0/doc/html/boost_process/… – Petroleum