Обнаружение смерти порожденного процесса с помощью Window CRT - PullRequest
1 голос
/ 22 января 2010

Резюме: мне нужен способ определить, умер ли процесс Windows, который я создал через _spawnl и взаимодействует с использованием FD из _pipe.

Подробности:

Яиспользование низкоуровневой функции CRT в Windows (_eof, _read) для связи с процессом, который был создан с помощью вызова _spawnl (с флагом P_NOWAIT).Я использую _pipe для создания файловых дескрипторов для связи с этим порожденным процессом и передаю эти дескрипторы (FD #) ему в командной строке.

Стоит отметить, что я не контролирую порожденный процесс,Для меня это черный ящик.

Оказывается, процесс, который мы порождаем, иногда падает.Я пытаюсь сделать мой код устойчивым к этому, обнаруживая сбой.К сожалению, я не вижу способа сделать это.Мне кажется разумным ожидать, что вызов _eof или _read для одного из этих дескрипторов вернет статус ошибки (-1), если процесс завершится.

К сожалению, это не так.Похоже, что дескрипторы живут своей жизнью независимо от порожденного процесса.Таким образом, хотя процесс на другом конце не работает, я не получаю статус ошибки в дескрипторе файла, который я использую для связи с ним.

У меня есть PID для вложенного процесса (возвращается из_spanwnl позвоните) но я не вижу ничего, что я могу сделать с этим.Мой код работает очень хорошо, за исключением одной вещи.Я не могу определить, занят ли порожденный процесс, вычисляя мне ответ или умер.

Если я смогу использовать информацию из _pipe и _spawnl, чтобы определить, мертв ли ​​порожденный процесс, я буду золотой.

Предложения очень приветствуются.

Заранее спасибо.

ОБНОВЛЕНИЕ : я нашел довольно простое решение и добавил его в качестве выбранного ответа.

Ответы [ 3 ]

1 голос
/ 09 апреля 2010

См Как узнать состояние дочернего процесса и использование ресурсов в Windows?

Вы можете просто использовать WaitForSingleObject для дескриптора, возвращенного из spawnl; у меня это нормально работает. Похоже, вы, возможно, уже пробовали это, но, возможно, я неправильно понимаю ваши ответы.

Пример кода, который порождает процесс и ожидает его завершения без использования _P_WAIT:

HANDLE hProcess = (HANDLE) _spawnl(_P_NOWAIT, "slave.exe", "slave.exe", NULL);
while(1)
{
  Sleep(100);
  if (WaitForSingleObject(hProcess, 0) == WAIT_OBJECT_0)
  {
    break;
  }
}
1 голос
/ 22 января 2010

Вам придется продвинуться по пищевой цепочке, если вы хотите быть в состоянии обнаружить, что процесс завершен. Встроенный Win32 API CreateProcess () может вернуть вам РУЧКУ, вы можете использовать его в API WaitForSingleObject () для ожидания или проверки, если процесс завершился. Если вы можете получить PID, вы можете использовать OpenProcess (), чтобы получить нужную РУЧКУ.

Другой подход заключается в использовании _P_WAIT для синхронного вызова. Это потребует потока.

0 голосов
/ 26 января 2010

Спасибо nobugz за много полезных советов. Я не закончил тем, что выбрал его путь «продвижения по пищевой цепочке», поэтому я пишу это как отдельный ответ, но это во многом результат его обратной связи.

Я использовал свой существующий вызов в spawnl. Оказывается, это было возможно, потому что при вызове в режиме P_NOWAIT возвращаемое значение фактически совпадает с OpenProcess. Это сбивает с толку, потому что spawnl имеет возвращаемый тип intptr_t, тогда как OpenProcess имеет возвращаемый тип HANDLE. Но они эквивалентны (по крайней мере, на основании моего тестирования).

Зная это, я все еще не был в лесу. Мне нужен был надежный способ определить, запущен ли процесс. Все различные вызовы, которые я делал с помощью дескриптора процесса (например, GetModuleBaseName), выполнялись успешно, даже когда процесс был мертв.

В конечном счете, я прибег к вызову GetProcessId (с моим дескриптором процесса), чтобы получить идентификатор процесса, а затем к вызову EnumerateProcesses и копанию результатов, возвращаемых из него, чтобы узнать, имеет ли какой-либо из этих запущенных процессов одинаковый идентификатор процесса.

Я бы признал, что использование API более высокого уровня (как предложил nobugz), вероятно, является общим путем. В моем случае у меня уже был весь работающий код, и мне нужно было только определить, работает ли вложенный процесс, поэтому я выбрал минималистский подход.

Еще раз спасибо nobugz за все полезные предложения.

...