mirror of
https://github.com/neovim/neovim.git
synced 2025-09-30 23:18:33 +00:00
[Backport release-0.7] introduce $NVIM, unset $NVIM_LISTEN_ADDRESS (#18986)
feat(server): introduce $NVIM
PROBLEM
------------------------------------------------------------------------
$NVIM_LISTEN_ADDRESS has conflicting purposes as both a parameter ("the
current process should listen on this address") and a descriptor ("the
current process is a child of this address").
This contradiction means the presence of NVIM_LISTEN_ADDRESS is
ambiguous, so child Nvim always tries to listen on its _parent's_
socket. This is the cause of lots of "Failed to start server" spam in
our test/CI logs:
WARN 2022-04-30… server_start:154: Failed to start server: address already in use: \\.\pipe\nvim-4480-0
WARN 2022-04-30… server_start:154: Failed to start server: address already in use: \\.\pipe\nvim-2168-0
SOLUTION
------------------------------------------------------------------------
1. Set $NVIM to the parent v:servername, *only* in child processes.
- Now the correct way to detect a "parent" Nvim is to check for $NVIM.
2. Do NOT set $NVIM_LISTEN_ADDRESS in child processes.
3. On startup if $NVIM_LISTEN_ADDRESS exists, unset it immediately after
server init.
4. Open a channel to parent automatically, expose it as v:parent.
Fixes #3118
Fixes #6764
Fixes #9336
Ref https://github.com/neovim/neovim/pull/8247#issuecomment-380275696
Ref #8696
(cherry picked from commit b9d97f5951
)
Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
This commit is contained in:
![41898282+github-actions[bot]@users.noreply.github.com](/assets/img/avatar_default.png)
committed by
GitHub

parent
ed9e6d19ab
commit
fdd5178581
@@ -16,6 +16,7 @@ local poke_eventloop = helpers.poke_eventloop
|
||||
local iswin = helpers.iswin
|
||||
local get_pathsep = helpers.get_pathsep
|
||||
local pathroot = helpers.pathroot
|
||||
local exec_lua = helpers.exec_lua
|
||||
local nvim_set = helpers.nvim_set
|
||||
local expect_twostreams = helpers.expect_twostreams
|
||||
local expect_msg_seq = helpers.expect_msg_seq
|
||||
@@ -208,7 +209,7 @@ describe('jobs', function()
|
||||
ok(string.find(err, "E475: Invalid argument: expected valid directory$") ~= nil)
|
||||
end)
|
||||
|
||||
it('produces error when using non-executable `cwd`', function()
|
||||
it('error on non-executable `cwd`', function()
|
||||
if iswin() then return end -- N/A for Windows
|
||||
|
||||
local dir = 'Xtest_not_executable_dir'
|
||||
@@ -249,7 +250,7 @@ describe('jobs', function()
|
||||
eq({'notification', 'exit', {0, 0}}, next_msg())
|
||||
end)
|
||||
|
||||
it('allows interactive commands', function()
|
||||
it('interactive commands', function()
|
||||
nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)")
|
||||
neq(0, eval('j'))
|
||||
nvim('command', 'call jobsend(j, "abc\\n")')
|
||||
@@ -295,7 +296,7 @@ describe('jobs', function()
|
||||
nvim('command', "call jobstop(j)")
|
||||
end)
|
||||
|
||||
it("will not buffer data if it doesn't end in newlines", function()
|
||||
it("emits partial lines (does NOT buffer data lacking newlines)", function()
|
||||
nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)")
|
||||
nvim('command', 'call jobsend(j, "abc\\nxyz")')
|
||||
eq({'notification', 'stdout', {0, {'abc', 'xyz'}}}, next_msg())
|
||||
@@ -378,7 +379,7 @@ describe('jobs', function()
|
||||
eq(NIL, meths.get_proc(pid))
|
||||
end)
|
||||
|
||||
it("do not survive the exit of nvim", function()
|
||||
it("disposed on Nvim exit", function()
|
||||
-- use sleep, which doesn't die on stdin close
|
||||
nvim('command', "let g:j = jobstart(has('win32') ? ['ping', '-n', '1001', '127.0.0.1'] : ['sleep', '1000'], g:job_opts)")
|
||||
local pid = eval('jobpid(g:j)')
|
||||
@@ -646,6 +647,43 @@ describe('jobs', function()
|
||||
)
|
||||
end)
|
||||
|
||||
it('jobstart() environment: $NVIM, $NVIM_LISTEN_ADDRESS #11009', function()
|
||||
local function get_env_in_child_job(envname, env)
|
||||
return exec_lua([[
|
||||
local envname, env = ...
|
||||
local join = function(s) return vim.fn.join(s, '') end
|
||||
local stdout = {}
|
||||
local stderr = {}
|
||||
local opt = {
|
||||
env = env,
|
||||
stdout_buffered = true,
|
||||
stderr_buffered = true,
|
||||
on_stderr = function(chan, data, name) stderr = data end,
|
||||
on_stdout = function(chan, data, name) stdout = data end,
|
||||
}
|
||||
local j1 = vim.fn.jobstart({ vim.v.progpath, '-es', '-V1',( '+echo "%s="..getenv("%s")'):format(envname, envname), '+qa!' }, opt)
|
||||
vim.fn.jobwait({ j1 }, 10000)
|
||||
return join({ join(stdout), join(stderr) })
|
||||
]],
|
||||
envname,
|
||||
env)
|
||||
end
|
||||
|
||||
local addr = eval('v:servername')
|
||||
ok((addr):len() > 0)
|
||||
-- $NVIM is _not_ defined in the top-level Nvim process.
|
||||
eq('', eval('$NVIM'))
|
||||
-- jobstart() shares its v:servername with the child via $NVIM.
|
||||
eq('NVIM='..addr, get_env_in_child_job('NVIM'))
|
||||
-- $NVIM_LISTEN_ADDRESS is unset by server_init in the child.
|
||||
eq('NVIM_LISTEN_ADDRESS=null', get_env_in_child_job('NVIM_LISTEN_ADDRESS'))
|
||||
eq('NVIM_LISTEN_ADDRESS=null', get_env_in_child_job('NVIM_LISTEN_ADDRESS',
|
||||
{ NVIM_LISTEN_ADDRESS='Xtest_jobstart_env' }))
|
||||
-- User can explicitly set $NVIM_LOG_FILE, $VIM, $VIMRUNTIME.
|
||||
eq('NVIM_LOG_FILE=Xtest_jobstart_env',
|
||||
get_env_in_child_job('NVIM_LOG_FILE', { NVIM_LOG_FILE='Xtest_jobstart_env' }))
|
||||
end)
|
||||
|
||||
describe('jobwait', function()
|
||||
before_each(function()
|
||||
if iswin() then
|
||||
|
Reference in New Issue
Block a user