Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Select which handles are inherited by child process

When creating a child process in C++ using Windows API, one can allow inheritance of handles from parent to child. In a Microsoft example "Creating a Child Process with Redirected Input and Output", redirecting a child process' std in/out to pipes created by the parent, it is necessary to allow inheritance for the redirection pipes to be usable.

I'm working on a small demo class that launches an external executable, reads the output, and then spits it back to the caller (who records the returned output to a file). I'm trying to build in a time-out feature, where it will only block for a certain amount of time before calling TerminateProcess() on the child and continuing on with life.

However, I've found that by allowing handle inheritance, the child process also has a handle (visible with Process Explorer) to the output file. I do not want the child process to obtain this handle, but the parent in this case (this demo class) is not aware of the handle either, so I cannot currently use SetHandleInformation() to unflag the output file specifically to exclude it from inheritance.

I am certain there must be a better way to inherit ONLY the specific handles that I want, without allowing "blanket" inheritance which passes unintended and undesired handles. Unfortunately I have been unable to find a solution, having browsed as many related MSDN articles as I can find, and having Googled myself into a state of discouragement.

At the very least, I need to do something to remove the handles from the child, without necessarily having those handles within the demo class (they're used by the calling class, and this demo class has no explicit knowledge of their existence).

Any solutions for more selective inheritance? I'm especially interested in the solution that allows me to specifically declare what handles to inherit, and all un-specified handles will not be inherited, if such a solution exists.

Thank you kindly.

like image 951
KevenK Avatar asked Feb 26 '10 21:02

KevenK


People also ask

What is inherited by child process?

A child process inherits the current directory of its parent process by default. However, CreateProcess enables the parent process to specify a different current directory for the child process. To change the current directory of the calling process, use the SetCurrentDirectory function.

Is userid inherited by a child process?

A child process created by the system and tpf_cresc functions inherits the environment list from the parent process. A child process created by the tpf_fork function inherits the following properties from the parent process: Environment list. Real user ID (UID) and real group ID (GID)

Which properties child process do not inherit from parent process?

* The child does not inherit process-associated record locks from its parent (fcntl(2)). (On the other hand, it does inherit fcntl(2) open file description locks and flock(2) locks from its parent.) * The child does not inherit timers from its parent (setitimer(2), alarm(2), timer_create(2)).


2 Answers

If the output file handle is inherited by the child process, then that is because the code in the parent process that opened the file explicitly stated that the file handle should be inheritable. It passed a value for the lpSecurityAttributes parameter of CreateFile. The default state is for the handle to not be inheritable.

It seems to me that your process-creating class shouldn't try to second-guess its caller, who has already opened the file.

However, if you have special knowledge of exactly which handles the new process needs, then as of Windows Vista, there is a mechanism for specifying which handles should be inherited. When you prepare to call CreateProcess, use a STARTUPINFOEX structure instead of the usual STARTUPINFO. It has an lpAttributeList member. Allocate and initialize it, and then use UpdateProcThreadAttribute with PROC_THREAD_ATTRIBUTE_HANDLE_LIST to set the list of handles to be inherited. All the handles need to be inheritable, and you still need to specify bInheritHandles = TRUE when you call CreateProcess. You also need to include EXTENDED_STARTUPINFO_PRESENT in the dwCreationFlags parameter. Raymond Chen demonstrated the technique in an article in 2011.

If that added functionality isn't available to you, then you could certainly try to enumerate all your program's open handles and set all their inheritance properties with SetHandleInformation, but that seems to be beyond the scope of a function whose job is to create child processes. Let the code that creates the handles worry about whether they should be inheritable.

like image 164
Rob Kennedy Avatar answered Sep 20 '22 08:09

Rob Kennedy


You can use SetHandleInformation to clear the HANDLE_FLAG_INHERIT bit on your output handle, this will prevent the child process from inheriting it.

If this flag is set, a child process created with the bInheritHandles parameter of CreateProcess set to TRUE will inherit the object handle.

like image 30
John Knoeller Avatar answered Sep 21 '22 08:09

John Knoeller