I am probably missing something but I consider handle inheritance as a key concept in creating child processes with redirected standard >input/output/error streams.
Well, this is what the option of inheriting handles is for, in the first place. However, unlike UNIX -like systems, this not not the kind of thing that you usually encounter in the Windows world, right…
I do not think the handles are automatically duplicated to the child process just because they are present in the STARTUPINFO structure, >their inheritance does just that.
According to the following link, std handles in the STARTUPINFO structure are ignored if STARTF_USESTDHANDLES flag is not set.
https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/ns-processthreadsapi-_startupinfoa
If this is the case, then setting STARTF_USESTDHANDLES flag in the STARTUPINFO structure, apparently, makes CreateProcess() call SetHandleInformation() on the target handles behind the scenes, effectively making the target handles inheritable.
At the same time, the link below indirectly suggests otherwise
https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-createprocessa
[begin quote]
Important The caller is responsible for ensuring that the standard handle fields in STARTUPINFO contain valid handle values. These fields are copied unchanged to the child process without validation, even when the dwFlags member specifies STARTF_USESTDHANDLES. Incorrect values can cause the child process to misbehave or crash. Use the Application Verifier runtime verification tool to detect invalid handles.
[end quote]
- create objects for handling standard input/output/error streams (e.g. pipes, regular opened files etc),
- set their handles inheritable as needed (you need to inherit “write” handle for stdout and stderr, “read” handle for stdin),
- specify the handles in the STARTUPINFO structure,
- call CreateProcess.
Taking into consideration yet another example of contradictions in the official documentation, I think this is,indeed, the most reasonable option
On *NIX systems, the advantage of fork() is that the child process sort of knows values of all handles (file descriptors)
inherited from the parent. But if the call is followed by exec() you pretty much get the same result as CreateProcess does
on Windows (including that file descriptor marked as “noninheritable” are closed).
Well, making a child immediately call exec() seems to defeat the very purpose of splitting the process creation in two stages, don’t you think…
Anton Bassov