Выберите, какие дескрипторы наследуются дочерним процессом - PullRequest
6 голосов
/ 27 февраля 2010

При создании дочернего процесса в C ++ с использованием Windows API можно разрешить наследование дескрипторов от родительского к дочернему. В примере Microsoft «Создание дочернего процесса с перенаправленным вводом и выводом» , перенаправляя std in / out дочернего процесса на каналы, созданные родительским процессом, необходимо разрешить наследование для каналов перенаправления годные к употреблению.

Я работаю над небольшим демонстрационным классом, который запускает внешний исполняемый файл, читает вывод, а затем выплевывает его обратно вызывающей стороне (которая записывает возвращенный вывод в файл). Я пытаюсь встроить функцию тайм-аута, где она будет блокироваться только на определенное время, прежде чем позвонить ребенку TerminateProcess() и продолжить жизнь.

Однако я обнаружил, что, разрешив наследование дескриптора, дочерний процесс также имеет дескриптор (видимый с Process Explorer ) для выходного файла. Я не хочу, чтобы дочерний процесс получил этот дескриптор, но родительский в этом случае (этот демонстрационный класс) также не знает о дескрипторе, поэтому в настоящее время я не могу использовать SetHandleInformation(), чтобы специально отключить выходной файл, чтобы исключить его из наследования .

Я уверен, что должен быть лучший способ наследовать ТОЛЬКО определенные дескрипторы, которые я хочу, без разрешения "общего" наследования, которое проходит непреднамеренные и нежелательные дескрипторы. К сожалению, я не смог найти решение, просмотрев столько статей, связанных с MSDN, сколько смогу найти, и заставил себя погуглить.

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

Какие-нибудь решения для более избирательного наследования? Меня особенно интересует решение, которое позволяет мне конкретно объявить, какие дескрипторы наследовать, и все неуказанные дескрипторы не будут наследоваться, если такое решение существует.

Спасибо, любезно.

Ответы [ 2 ]

3 голосов
/ 27 февраля 2010

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

Мне кажется, что ваш класс, создающий процесс, не должен пытаться угадать своего вызывающего, который уже открыл файл.

Однако, если вы обладаете особыми знаниями о том, какие именно обрабатывает новые потребности процесса, то в Windows Vista существует механизм указания, какие дескрипторы должны быть унаследованы. При подготовке к вызову CreateProcess используйте структуру STARTUPINFOEX вместо обычной STARTUPINFO. Он имеет lpAttributeList член. Выделите и инициализируйте его, а затем используйте UpdateProcThreadAttribute с PROC_THREAD_ATTRIBUTE_HANDLE_LIST, чтобы установить список дескрипторов для наследования. Все дескрипторы должны быть наследуемыми, и вам все равно нужно указать bInheritHandles = true при вызове CreateProcess. Вам также необходимо включить EXTENDED_STARTUPINFO_PRESENT в параметр dwCreationFlags. Рэймонд Чен продемонстрировал эту технику в статье в 2011 году.

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

1 голос
/ 27 февраля 2010

Вы можете использовать SetHandleInformation , чтобы очистить бит HANDLE_FLAG_INHERIT на вашем дескрипторе вывода, это предотвратит наследование дочерним процессом.

Если этот флаг установлен, дочерний процесс, созданный с параметром bInheritHandles в CreateProcess со значением TRUE, будет наследовать дескриптор объекта.

...