fix(process): avoid unexpected behavior when PTY chdir failed (#37614)

Problem:  Unexpected behavior after PTY child process fails to chdir(),
          as it then thinks it's the parent process.
Solution: Exit the child process instead of returning.
This commit is contained in:
zeertzjq
2026-01-29 22:02:24 +08:00
committed by GitHub
parent 484f455402
commit 19a3b67789
2 changed files with 31 additions and 7 deletions

View File

@@ -263,7 +263,7 @@ void pty_proc_teardown(Loop *loop)
}
static void init_child(PtyProc *ptyproc)
FUNC_ATTR_NONNULL_ALL
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NORETURN
{
#if defined(HAVE__NSGETENVIRON)
# define environ (*_NSGetEnviron())
@@ -285,7 +285,7 @@ static void init_child(PtyProc *ptyproc)
// Don't use os_chdir() as that may buffer UI events unnecessarily.
if (proc->cwd && (err = uv_chdir(proc->cwd)) != 0) {
ELOG("chdir(%s) failed: %s", proc->cwd, uv_strerror(err));
return;
_exit(122);
}
const char *prog = proc_get_exepath(proc);

View File

@@ -297,18 +297,42 @@ describe('jobs', function()
end)
it('error on non-executable `cwd`', function()
if is_os('win') then
return -- Not applicable for Windows.
end
skip(is_os('win'), 'N/A for Windows')
local dir = 'Xtest_not_executable_dir'
mkdir(dir)
finally(function()
rmdir(dir)
end)
fn.setfperm(dir, 'rw-------')
matches(
'^Vim%(call%):E903: Process failed to start: permission denied: .*',
pcall_err(command, "call jobstart(['pwd'], {'cwd': '" .. dir .. "'})")
pcall_err(command, ("call jobstart(['pwd'], {'cwd': '%s'})"):format(dir))
)
rmdir(dir)
end)
it('error log and exit status 122 on non-executable `cwd`', function()
skip(is_os('win'), 'N/A for Windows')
local logfile = 'Xchdir_fail_log'
clear({ env = { NVIM_LOG_FILE = logfile } })
local dir = 'Xtest_not_executable_dir'
mkdir(dir)
finally(function()
rmdir(dir)
n.check_close()
os.remove(logfile)
end)
fn.setfperm(dir, 'rw-------')
n.exec(([[
let s:chan = jobstart(['pwd'], {'cwd': '%s', 'pty': v:true})
let g:status = jobwait([s:chan], 1000)[0]
]]):format(dir))
eq(122, eval('g:status'))
t.assert_log(('chdir%%(%s%%) failed: permission denied'):format(dir), logfile, 100)
end)
it('returns 0 when it fails to start', function()