From 1949452bd3607e36b49b72ee639938f134eaca23 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 21 Jan 2026 11:53:18 +0800 Subject: [PATCH] fix(tui): avoid using uv_pipe_t as uv_tty_t (#37479) Check tui->out_isatty before accessing tui->output_handle.tty. --- src/nvim/tui/tui.c | 2 +- test/functional/terminal/tui_spec.lua | 20 ++++++++------------ 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c index 9b3bf332b7..58d9d56789 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -1389,7 +1389,7 @@ void tui_mode_change(TUIData *tui, String mode, Integer mode_idx) // If stdin is not a TTY, the LHS of pipe may change the state of the TTY // after calling uv_tty_set_mode. So, set the mode of the TTY again here. // #13073 - if (tui->is_starting && !stdin_isatty) { + if (tui->out_isatty && tui->is_starting && !stdin_isatty) { int ret = uv_tty_set_mode(&tui->output_handle.tty, UV_TTY_MODE_NORMAL); if (ret) { ELOG("uv_tty_set_mode failed: %s", uv_strerror(ret)); diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua index a82fed1708..09ac12b0ab 100644 --- a/test/functional/terminal/tui_spec.lua +++ b/test/functional/terminal/tui_spec.lua @@ -4023,7 +4023,7 @@ describe('TUI client', function() screen_client:expect({ any = vim.pesc('[Process exited 0]') }) end) - local function start_headless_server_and_client() + local function start_headless_server_and_client(use_testlog) local server = n.new_session(false, { args_rm = { '--cmd' }, args = { @@ -4033,7 +4033,8 @@ describe('TUI client', function() nvim_set .. ' notermguicolors background=dark', }, }) - local client_super = n.new_session(true, { env = { NVIM_LOG_FILE = testlog } }) + local client_super = + n.new_session(true, use_testlog and { env = { NVIM_LOG_FILE = testlog } } or {}) finally(function() client_super:close() server:close() @@ -4062,7 +4063,7 @@ describe('TUI client', function() end it('connects to remote instance (--headless)', function() - local server, server_pipe, screen_client = start_headless_server_and_client() + local server, server_pipe, screen_client = start_headless_server_and_client(false) -- No heap-use-after-free when receiving UI events after deadly signal #22184 server:request('nvim_input', ('a'):rep(1000)) @@ -4077,6 +4078,7 @@ describe('TUI client', function() eq(0, api.nvim_get_vvar('shell_error')) -- exits on input eof #22244 + -- Use system() without input so that stdin is closed. fn.system({ nvim_prog, '--remote-ui', '--server', server_pipe }) eq(1, api.nvim_get_vvar('shell_error')) @@ -4095,16 +4097,10 @@ describe('TUI client', function() feed_data(':echo "GUI Running: " .. has("gui_running")\013') screen_client:expect({ any = 'GUI Running: 0' }) - - if is_os('mac') then - -- this might either be "Unknown system error %-102" or - -- "inappropriate ioctl for device" depending on the phase of the moon - assert_log('uv_tty_set_mode failed', testlog) - end end) it(':restart works when connecting to remote instance (--headless)', function() - local _, server_pipe, screen_client = start_headless_server_and_client() + local _, server_pipe, screen_client = start_headless_server_and_client(false) -- Run :restart on the client. -- The client should start a new server while the original server should exit. @@ -4127,7 +4123,7 @@ describe('TUI client', function() end) it('does not crash or hang with a very long title', function() - local server, _, screen_client = start_headless_server_and_client() + local server, _, screen_client = start_headless_server_and_client(true) local server_exec_lua = tt.make_lua_executor(server) if not server_exec_lua('return pcall(require, "ffi")') then @@ -4165,7 +4161,7 @@ describe('TUI client', function() end) it('nvim_ui_send works with remote client #36317', function() - local server, _, _ = start_headless_server_and_client() + local server, _, _ = start_headless_server_and_client(false) server:request('nvim_ui_send', '\027]2;TEST_TITLE\027\\') retry(nil, nil, function() eq('TEST_TITLE', api.nvim_buf_get_var(0, 'term_title'))