CreateProcess так, что дочерний процесс убит, когда родительский убит?

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

Возможно, используя флаги Create Process?

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

6 ответов

Решение

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

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

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

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

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

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

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

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

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

Другие вопросы по тегам