0
votes

I can use STARTF_USESTDHANDLES flag in STARTUPINFO structure to redirect stdin, stdout, stderr of process, created by CreateProcess.

Documentation says for this case (STARTF_USESTDHANDLES flag present):

The hStdInput, hStdOutput, and hStdError members contain additional information. If this flag is specified when calling one of the process creation functions, the handles must be inheritable and the function's bInheritHandles parameter must be set to TRUE. For more information, see Handle Inheritance.

But for those members itself (hStdInput etc) the same doc says (for example - hStdError):

If dwFlags specifies STARTF_USESTDHANDLES, this member is the standard error handle for the process. Otherwise, this member is ignored and the default for standard error is the console window's buffer.

If I would connect pipe to child process stdout and do not read data from it, its buffer will overflow and according to this doc, the child prcess will hang after a while on attempt to write data on stdout, because

If the pipe buffer is full before all bytes are written, WriteFile does not return until another process or thread uses ReadFile to make more buffer space available.

Can I safely pass NULL for hStdOutput and hStdError members of STARTUPINFO struct when STARTF_USESTDHANDLES flag is present to avoid such situation? Or I must make polling thread to wipe data from pipe to pervent its buffer overflowing?

I want reliable solution, so please, could you post any ref to documentation says that this is legal way to drop data from stdout.

1

1 Answers

2
votes

Open the NUL device and use that as the hStdOutput and hStrError handles. Any data written to the NUL device will be ignored without causing errors. This is preferable than having no handle, as write failures to standard output or standard error in the child processes might cause it to exit prematurely. Be sure to make the handle inheritable as the documentation mentioned.

Something like:

SECURITY_ATTRIBUTES secattr;
secattr.nLength = sizeof secattr;
secattr.lpSecurityDescriptor = NULL;
secattr.bInheritHandle = TRUE;
hnul = CreateFile("NUL", GENERIC_WRITE, 0, &secattr, OPEN_EXISTING, 0, NULL);
startupinfo.hStdOutput = hnul;
startupinfo.hStdError = hnul;

I'm not sure if the NUL device is officially documented by Microsoft anywhere. However it's been part of Windows since before there was Windows. MS-DOS 1.0 supported it. It works like Unix's /dev/null, if you're familiar with that.