From: Muraoka Taro Date: Sat, 27 Dec 2025 14:36:31 +0000 (+0000) Subject: patch 9.1.2025: conpty terminal process may not start X-Git-Tag: v9.1.2025^0 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9f5b09ea1f37c9555bea1d950916bc94d271f68c;p=thirdparty%2Fvim.git patch 9.1.2025: conpty terminal process may not start Problem: Conpty terminal process may not start. Solution: Do not close the input handle at EOF when conpty is in use. (Muraoka Taro) It causes the following tests to fail in Windows conpty: - Test_terminal_duplicate_eof_arg() - Test_terminal_eof_arg() - Test_terminal_eof_arg_win32_ctrl_z() To be precise, the process is launched, but immediately after it is launched, the input handle to the console is closed with the EOF of the input, and the console is terminated. When the console is terminated, the associated process is also terminated. In the Windows pseudo console, input and output handles are closed after the process in the console has terminated. This is not explicitly stated in Microsoft's documentation. However, looking at the code for Windows Terminal, which is presented as a complete example of the pseudo console, it is implemented exactly this way. See the sample codes below: - https://github.com/microsoft/terminal/blob/main/samples/ConPTY/EchoCon/EchoCon/EchoCon.cpp - https://github.com/microsoft/terminal/blob/main/samples/ConPTY/GUIConsole/GUIConsole.ConPTY/Terminal.cs - https://github.com/microsoft/terminal/blob/main/samples/ConPTY/MiniTerm/MiniTerm/Terminal.cs The handle that is not closed at EOF is closed when Vim detects the end of the job, so there is no risk of them being forgotten and leaking. `ch_anonymous_pipe`, which was used to determine whether a channel was for conpty, was set to TRUE only when conpty was being used. The definition also had the comment `// ConPTY` attached to it. This name is not very appropriate, but I felt it would be rude to add a new field to `channel_T` just for this purpose, so I reused it. closes: #19025 Signed-off-by: Muraoka Taro Signed-off-by: Christian Brabandt --- diff --git a/src/channel.c b/src/channel.c index 0d639f5227..1248adb174 100644 --- a/src/channel.c +++ b/src/channel.c @@ -1635,7 +1635,14 @@ channel_write_in(channel_T *channel) ch_log(channel, "Finished writing all lines to channel"); // Close the pipe/socket, so that the other side gets EOF. - ch_close_part(channel, PART_IN); +#ifdef MSWIN + // At this point, the input part of the conpty channel must not be + // closed. If it is closed, the pipe will be destroyed, the console + // that was using it will be destroyed, and the process running within + // it will be forcibly terminated, so this needs to be prevented. + if (!channel->ch_anonymous_pipe) +#endif + ch_close_part(channel, PART_IN); } else ch_log(channel, "Still %ld more lines to write", diff --git a/src/terminal.c b/src/terminal.c index 0e7dc87ddb..234807e904 100644 --- a/src/terminal.c +++ b/src/terminal.c @@ -7167,6 +7167,8 @@ conpty_term_and_job_init( channel->ch_write_text_mode = TRUE; // Use to explicitly delete anonymous pipe handle. + // In addition, it is used to prevent the pipe from being closed when input + // from a buffer etc. is finished. channel->ch_anonymous_pipe = TRUE; jo = CreateJobObject(NULL, NULL); diff --git a/src/version.c b/src/version.c index f09ff17915..7f80ccf5b4 100644 --- a/src/version.c +++ b/src/version.c @@ -734,6 +734,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2025, /**/ 2024, /**/