В ожидании boost::process::child
как узнать, вышел ли он «изящно или нет»?
Допустим, я создаю процесс:
boost::process::child child( "myprg.exe", "5000" );
child.wait();
int res = child.exit_code();
Где myprg.exe:
int main( int argc, char* argv[] )
{
if ( argc == 2 )
{
boost::this_thread::sleep( boost::posix_time::milliseconds( atoi( argv[1] ) ) );
return 1;
}
return 0;
}
Примечание: это MCVE, который не имеет смысла, я согласен, что main должен вернуть 0 в случае успеха.
Я вижу, что если кто-то убивает процесс, пока он ждет (используя child.terminate
например или диспетчер процессов Windows), child.exit_code()
вернет 1.
Итак, в конце концов, когда child.exit_code()
равно 1, как я могу узнать, является ли это значение, возвращаемое основной функцией входа процесса, или процесс был убит?
Гарантируется, что 1 будет означать, что процесс был убит? Тогда программа не должна возвращать 1 и сохранять этот код завершения, чтобы определить конкретную ситуацию, в которой она была убита и не была завершена корректно?
Если нет, делает boost::process
API предоставляет что-то, чтобы узнать, был ли процесс закончен чисто или был убит?
Итак, в конце концов, когда
child.exit_code()
равно 1, как я могу узнать, является ли это значение, возвращаемое основной функцией входа процесса, или процесс был убит?
Ты не можешь
Гарантируется, что 1 будет означать, что процесс был убит?
Это зависит. Что касается Windows, в соответствии с этот ответ, это будет 1, но это нигде не задокументировано. Обратите внимание, что код возврата для уничтоженного процесса определяется экземпляром, завершающим процесс. Для терминаторной функции Boost можно найти внутри 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_; }
Так что возвращается EXIT_FAILURE
всегда, что может быть 1. Однако, процесс может вернуть любое значение.
Чтобы отличить, завершился ли ваш процесс изящно или нет полностью безошибочным и переносимым способом, вам необходимо реализовать собственный механизм связи, помимо оценки кодов возврата.
Вы можете установить обработчик ошибок в дочернем процессе, чтобы он возвращал другой код завершения. Например, добавить станд :: set_terminate из библиотеки STL:
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;
}