Skip to content

Process_WIN32U: PROCESS_CLOSE_STD* flags close parent's handles instead of child's #5191

@matejk

Description

@matejk

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

Metadata

Metadata

Assignees

Type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions