Как узнать, когда процесс вышел «изящно или нет»?

В ожидании 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 предоставляет что-то, чтобы узнать, был ли процесс закончен чисто или был убит?

2

Решение

Итак, в конце концов, когда 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. Однако, процесс может вернуть любое значение.

Чтобы отличить, завершился ли ваш процесс изящно или нет полностью безошибочным и переносимым способом, вам необходимо реализовать собственный механизм связи, помимо оценки кодов возврата.

2

Другие решения

Вы можете установить обработчик ошибок в дочернем процессе, чтобы он возвращал другой код завершения. Например, добавить станд :: 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;
}
0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector