Description
In Foundation/src/Process_WIN32U.cpp, the PROCESS_CLOSE_STDIN, PROCESS_CLOSE_STDOUT, and PROCESS_CLOSE_STDERR options incorrectly close the parent process's standard handles using GetStdHandle(), instead of closing the duplicated handles in startupInfo that are about to be inherited by the child process.
Current behavior
if (options & PROCESS_CLOSE_STDOUT)
{
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
if (hStdOut) CloseHandle(hStdOut);
}
This calls GetStdHandle(STD_OUTPUT_HANDLE) which returns the calling (parent) process's stdout handle, then closes it. After this, any write to std::cout or std::cerr in the parent process crashes or fails silently.
The same issue affects PROCESS_CLOSE_STDIN and PROCESS_CLOSE_STDERR.
Expected behavior
The flags should close the duplicated handles in startupInfo that were prepared for the child process, preventing the child from inheriting them — without affecting the parent:
if (options & PROCESS_CLOSE_STDOUT)
{
if (startupInfo.hStdOutput) CloseHandle(startupInfo.hStdOutput);
startupInfo.hStdOutput = 0;
}
Comparison with POSIX implementation
The POSIX implementation (Process_UNIX.cpp) handles this correctly. The close(STDOUT_FILENO) etc. calls happen inside the child process after fork() (in the else branch of fork()), so they only affect the child:
// Process_UNIX.cpp — runs in child process after fork()
if (options & PROCESS_CLOSE_STDIN) close(STDIN_FILENO);
// ...
if (options & PROCESS_CLOSE_STDOUT) close(STDOUT_FILENO);
// ...
if (options & PROCESS_CLOSE_STDERR) close(STDERR_FILENO);
On Windows there is no fork(), so the equivalent is to close the duplicated startupInfo handles before calling CreateProcessW() — these are the handles that will be inherited by the child. Using GetStdHandle() instead erroneously targets the parent's own handles.
Reproduction
Launch a child process with PROCESS_CLOSE_STDOUT | PROCESS_CLOSE_STDERR flags, then write to std::cerr in the parent process — the parent crashes.
Environment
- Windows (affects
Process_WIN32U.cpp only; POSIX code paths are not affected)
- Discovered in POCO 1.14.2-based fork, but the code appears unchanged in current main
Description
In
Foundation/src/Process_WIN32U.cpp, thePROCESS_CLOSE_STDIN,PROCESS_CLOSE_STDOUT, andPROCESS_CLOSE_STDERRoptions incorrectly close the parent process's standard handles usingGetStdHandle(), instead of closing the duplicated handles instartupInfothat are about to be inherited by the child process.Current behavior
This calls
GetStdHandle(STD_OUTPUT_HANDLE)which returns the calling (parent) process's stdout handle, then closes it. After this, any write tostd::coutorstd::cerrin the parent process crashes or fails silently.The same issue affects
PROCESS_CLOSE_STDINandPROCESS_CLOSE_STDERR.Expected behavior
The flags should close the duplicated handles in
startupInfothat were prepared for the child process, preventing the child from inheriting them — without affecting the parent:Comparison with POSIX implementation
The POSIX implementation (
Process_UNIX.cpp) handles this correctly. Theclose(STDOUT_FILENO)etc. calls happen inside the child process afterfork()(in theelsebranch offork()), so they only affect the child:On Windows there is no
fork(), so the equivalent is to close the duplicatedstartupInfohandles before callingCreateProcessW()— these are the handles that will be inherited by the child. UsingGetStdHandle()instead erroneously targets the parent's own handles.Reproduction
Launch a child process with
PROCESS_CLOSE_STDOUT | PROCESS_CLOSE_STDERRflags, then write tostd::cerrin the parent process — the parent crashes.Environment
Process_WIN32U.cpponly; POSIX code paths are not affected)