jpo38
jpo38

Reputation: 21514

boost::process how to know when a process exited "gracefully or not"?

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

Answers (2)

Nayfe
Nayfe

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

Jodocus
Jodocus

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

Related Questions