neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

commit a7a7cdbcda1f0ef5a29742aea973d2d1c0bfa9a0
parent 1ed064625c1cb71161c4683c5cb0b2d19bf3c091
Author: glepnir <glephunter@gmail.com>
Date:   Fri, 13 Feb 2026 19:29:48 +0800

fix(cmd): filter stdin file "-" from v:argv on :restart #37165

Problem:
restart hangs when nvim was started with stdin input, "-" marker stays
in v:argv, causing the restarted instance to block reading from stdin.

Solution:
filter out the "-" argument when rebuilding v:argv during restart.
Stdin content is ephemeral and shouldn't be re-read after restart.
Diffstat:
Msrc/nvim/ex_docmd.c | 46+++++++++++++++++++++++++---------------------
Mtest/functional/terminal/tui_spec.lua | 48++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 73 insertions(+), 21 deletions(-)

diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c @@ -4940,27 +4940,31 @@ static void ex_quitall(exarg_T *eap) /// ":restart +cmd <command>": restart the Nvim server using ":cmd" and add -c <command> to the new server. static void ex_restart(exarg_T *eap) { - // Patch v:argv to include "-c <arg>" when it restarts. - if (eap->arg != NULL) { - const list_T *l = get_vim_var_list(VV_ARGV); - int argc = tv_list_len(l); - list_T *argv_cpy = tv_list_alloc(argc + 2); - bool added_startup_arg = false; - TV_LIST_ITER_CONST(l, li, { - const char *arg = tv_get_string(TV_LIST_ITEM_TV(li)); - size_t arg_size = strlen(arg); - assert(arg_size <= (size_t)SSIZE_MAX); - tv_list_append_string(argv_cpy, arg, (ssize_t)arg_size); - if (!added_startup_arg) { - tv_list_append_string(argv_cpy, "-c", 2); - size_t cmd_size = strlen(eap->arg); - assert(cmd_size <= (size_t)SSIZE_MAX); - tv_list_append_string(argv_cpy, eap->arg, (ssize_t)cmd_size); - added_startup_arg = true; - } - }); - set_vim_var_list(VV_ARGV, argv_cpy); - } + const list_T *l = get_vim_var_list(VV_ARGV); + int argc = tv_list_len(l); + list_T *argv_cpy = tv_list_alloc(eap->arg ? argc + 2 : argc); + bool added_startup_arg = false; + + TV_LIST_ITER_CONST(l, li, { + const char *arg = tv_get_string(TV_LIST_ITEM_TV(li)); + size_t arg_size = strlen(arg); + assert(arg_size <= (size_t)SSIZE_MAX); + // Skip "-" argument (stdin input marker). + if (strequal(arg, "-")) { + continue; + } + + tv_list_append_string(argv_cpy, arg, (ssize_t)arg_size); + + // Patch v:argv to include "-c <arg>" when it restarts. + if (eap->arg && !added_startup_arg) { + tv_list_append_string(argv_cpy, "-c", 2); + tv_list_append_string(argv_cpy, eap->arg, (ssize_t)strlen(eap->arg)); + added_startup_arg = true; + } + }); + + set_vim_var_list(VV_ARGV, argv_cpy); char *quit_cmd = (eap->do_ecmd_cmd) ? eap->do_ecmd_cmd : "qall"; char *quit_cmd_copy = NULL; diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua @@ -428,6 +428,54 @@ describe('TUI :restart', function() restart_pid_check() gui_running_check() end) + + it('filters stdin marker from v:argv on restart #34417', function() + t.skip(is_os('win'), 'stdin behavior differs on Windows') + clear() + local server_session + finally(function() + if server_session then + server_session:close() + end + n.check_close() + end) + local server_pipe = new_pipename() + local screen = tt.setup_child_nvim({ + '-u', + 'NONE', + '-i', + 'NONE', + '--listen', + server_pipe, + '--cmd', + 'set notermguicolors', + '-', + }) + screen:expect([[ + ^ | + ~ |*3 + {2:[No Name] [RO] 1,0-1 All}| + | + {5:-- TERMINAL --} | + ]]) + server_session = n.connect(server_pipe) + local expr = 'index(v:argv, "-") >= 0 ? v:true : v:false' + local _, has_stdin = server_session:request('nvim_eval', expr) + eq(true, has_stdin) + + tt.feed_data(':restart\013') + screen:expect([[ + ^ | + ~ |*3 + {2:[No Name] 0,0-1 All}| + | + {5:-- TERMINAL --} | + ]]) + server_session:close() + server_session = n.connect(server_pipe) + local _, has_stdin_after = server_session:request('nvim_eval', expr) + eq(false, has_stdin_after) + end) end) describe('TUI :connect', function()