CreateProcess так, что дочерний процесс убит, когда родительский убит? - PullRequest
14 голосов
/ 07 июня 2011

Есть ли способ вызвать CreateProcess , чтобы при уничтожении родительского процесса дочерний процесс автоматически убивался?

Возможно, используя Создать флаги процесса ?

Редактировать
Решение состоит в том, чтобы создать объект задания, поместить родительский и дочерний объекты в объект задания. Когда его родитель убит, ребенок убит. Я получил код отсюда: Убить дочерний процесс при уничтожении родительского процесса Обратите внимание на комментарий @ wilx о унаследованных дескрипторах.

Ответы [ 6 ]

8 голосов
/ 07 июня 2011

Использование заданий в качестве Нил говорит, что - ИМХО лучший способ.Вы можете сделать так, чтобы дочерние процессы были уничтожены, когда умирает владелец процесса, установив JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE для объекта задания, используя SetInformationJobObject().Дескриптор объекта задания будет закрыт, когда ваш родительский процесс завершится / умрет.Чтобы это работало, важно, чтобы дескриптор задания не был унаследован дочерними процессами.Если вы хотите также отслеживать процессы потомок, вам нужно будет приостановить дочерние процессы, добавить их в объект задания и только после этого запускать.

5 голосов
/ 07 июня 2011

Лучшее, что вы можете сделать, - это поместить оба процесса в одно и то же задание, чтобы уничтожение задания убило оба процесса.

4 голосов
/ 07 июня 2011

Требуется ли, чтобы дочерний процесс был уничтожен , или просто обнаружил выход родительского процесса, чтобы он мог завершиться чисто? Родительский процесс может создать для себя наследуемый дескриптор, который потом потом может передать WaitForMultipleObjects(Ex) вместе со своими собственными объектами.

Если дочерний процесс не написан специально для этого, вы можете присоединить его stdin к каналу, другой конец которого удерживается родительским процессом. Если родитель умирает, канал автоматически закрывается.

Это близко соответствует поведению Unix, в котором ребенок не убивается, когда его родитель умирает, он обычно выходит в ответ на SIGHUP (но он может обрабатывать этот сигнал и реализовывать любое поведение). В Linux родительский PID сироты изменяется на 1 (init).

1 голос
/ 15 августа 2017

Другой подход

Бесполезно в всех ситуациях, однако у меня был один конкретный сценарий, когда приложение полностью контролировало дочерний процесс. Для связи и перехвата API потребовалась инъекция DLL, поэтому в реальных дочерних процессах DLL работает, чтобы отчитываться перед родителем.

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

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

Если вы управляете дочерними процессами и в любом случае имеете внедренную DLL, вы можете расширить эту DLL с помощью , отслеживая родительский процесс, чтобы проверить, запущен ли он. Если нет, ExitProcess.

Если вам не нужна DLL в дочернем процессе, другие решения, скорее всего, будут намного лучше.


Вы можете передать parentProcessID, например, через ключ реестра, который вы уже используете в своем приложении. Или вы можете передать командную строку, если это не нарушает дочерний процесс.

Это должно выполняться в своем собственном потоке. В моей DLL было два потока: здесь этот код и код управления и связи.

DLL

bool IsProcessRunning(HANDLE hProcess)
{
    DWORD exitCode;
    GetExitCodeProcess(hProcess, &exitCode);
    return exitCode == STILL_ACTIVE;
}

bool WINAPI DllMain(HINSTANCE hInstDll, DWORD fdwReason, LPVOID lpvReserved)
{
    if (fdwReason == DLL_PROCESS_ATTACH)
    {
        int parentProcessID = [...]

        HANDLE parentProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, TRUE, parentProcessID);
        while (IsProcessRunning(parentHandle)) Sleep(100);
        ExitProcess(0);
    }

    return true;
}
1 голос
/ 07 июня 2011

Полагаю, DEBUG_PROCESS или DEBUG_ONLY_THIS_PROCESS сделали бы это почти случайным побочным эффектом.Windows не создает процессы в дереве, как это делают Unix-подобные системы.

0 голосов
/ 07 июня 2011

Не знаю о Windows, но это будет работать на Linux: prctl (PR_SET_PDEATHSIG, SIGHUP);

...