Reputation: 21514
While waiting for a boost::process::child
, how can you know if it exited "gracefully or not"?
Let's say I create a processus:
boost::process::child child( "myprg.exe", "5000" );
child.wait();
int res = child.exit_code();
Where myprg.exe is:
int main( int argc, char* argv[] )
{
if ( argc == 2 )
{
boost::this_thread::sleep( boost::posix_time::milliseconds( atoi( argv[1] ) ) );
return 1;
}
return 0;
}
Note: This a MCVE that makes no sense, I agree main should return 0 if successfull.
I see that if someone kills the process while it waits (using child.terminate
for instance or Windows Process Manager), child.exit_code()
will return 1.
So, in the end, when child.exit_code()
is 1, how can I know if this is the value returned by the process's main entry function or if the process was killed?
Is it guaranteed that 1 will mean process was killed? Then program should not return 1 and keep this exit code to identify the specific situation where it was killed and did not exit cleanly?
If not, does boost::process
API provide something to know if process ended up cleanly or was killed?
Upvotes: 2
Views: 2151
Reputation: 2310
You can set an error handler in child process to return a different exit code. For instance, add std::set_terminate from STL library :
int main( int argc, char* argv[] )
{
std::set_terminate([](){ exit(2); });
if ( argc == 2 )
{
boost::this_thread::sleep(boost::posix_time::milliseconds(atoi(argv[1])));
return 1;
}
return 0;
}
Upvotes: 0
Reputation: 7601
So, in the end, when
child.exit_code()
is 1, how can I know if this is the value returned by the process's main entry function or if the process was killed?
You can't.
Is it guaranteed that 1 will mean process was killed?
It depends. As for Windows, according to this answer, it will be 1, but it is documented nowhere. Note that the return code for a killed process is determined by the instance that is terminating the process. For Boost's terminate function, one finds inside detail/windows/terminate.hpp:
inline void terminate(child_handle &p) { if (!::boost::winapi::TerminateProcess(p.process_handle(), EXIT_FAILURE)) boost::process::detail::throw_last_error("TerminateProcess() failed"); ::boost::winapi::CloseHandle(p.proc_info.hProcess); p.proc_info.hProcess = ::boost::winapi::INVALID_HANDLE_VALUE_; }
So it is returning EXIT_FAILURE
always, which might be 1. However, one can make a process return any value.
To distinguish whether your process terminated gracefully or not in a completely foolproof and portable manner, you therefore have to implement your own communication mechanism apart from just evaluating the return codes.
Upvotes: 2