http://bugs.winehq.org/show_bug.cgi?id=58967
Bug ID: 58967 Summary: ConPTY: Child process inherits parent's std handles instead of connecting to the pseudoconsole Product: Wine Version: unspecified Hardware: x86-64 OS: Linux Status: UNCONFIRMED Severity: normal Priority: P2 Component: -unknown Assignee: wine-bugs@list.winehq.org Reporter: unxed@mail.ru Distribution: ---
Created attachment 79673 --> http://bugs.winehq.org/attachment.cgi?id=79673 conpty_ping_test.c
Observed behavior:
When a process is created with the PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE attribute (using the ConPTY API), it incorrectly inherits the standard input/output handles (stdin/stdout/stderr) from its parent process.
What is the expected behavior:
The child process's standard handles should be connected to the pseudoconsole session provided by CreatePseudoConsole. Its output should be redirected to the ConPTY output pipe, not to the parent's stdout. This is the standard behavior on Windows.
Steps to reproduce:
1. Compile the attached C program (conpty_ping_test.c). This program: a. Creates a pseudoconsole using CreatePseudoConsole. b. Creates pipes for the pseudoconsole's I/O. c. Launches a child process (ping.exe) using CreateProcessW with the PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE attribute set. d. Reads from the ConPTY output pipe and prints the data to its own stdout.
2. Run the compiled program from a terminal: wine conpty_ping_test.exe > conpty_ping_test.log
Observed results:
The host program's read loop terminates immediately, indicating that the ConPTY output pipe was closed without any data being written to it. Then, the full output of ping.exe is printed directly to the terminal.
Example output:
Pseudoconsole created successfully. Process 'ping 127.0.0.1 -n 4' started with PID: 1240 --- Start of process output ---
[DEBUG] Pipe closed by the child process. Exiting read loop.
--- End of process output --- Waiting for the child process to exit... Pinging 127.0.0.1 [127.0.0.1] with 32 bytes of data: PING: transmit failed. General failure. PING: transmit failed. General failure. PING: transmit failed. General failure. PING: transmit failed. General failure.
Ping statistics for 127.0.0.1 Packets: Sent = 4, Received = 0, Lost = 4 (100% loss) Process finished with exit code: 0 All resources have been freed. Exiting.
This demonstrates that ping.exe's stdout was inherited from the host process (conpty_ping_test.c) rather than being attached to the pseudoconsole.
This issue seems to stem from how the C-runtime (CRT) of the child process (ping.exe) initializes its standard handles. On Windows, the CRT detects the ConPTY session via the ConsoleHandle in the process parameters and connects its stdio to it by opening CONIN$ and CONOUT$.
In Wine, it appears the CRT initialization code for msvcrt does not correctly handle this case and falls back to inheriting the parent's file handles.
This is different from Wine's own conhost/tests/tty.c test, which works because the child process explicitly calls CreateFile("CONOUT$"), bypassing the problematic CRT initialization logic. The attached test case reproduces the scenario of a standard, unmodified console application like ping.exe.
This bug makes the ConPTY API unusable for its primary purpose: capturing the I/O of external console applications.