diff options
author | Justin M. Keyes <justinkz@gmail.com> | 2022-05-03 15:08:35 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-05-03 06:08:35 -0700 |
commit | 4fb48c5654d9ffbffbdcdd80d0498b1ea3c8e68b (patch) | |
tree | 8a1222f6ed9a170ca2d151afcd911dfd01affdaf /src/nvim/msgpack_rpc/server.c | |
parent | b5c15ba7e5266bdd742a835d82525d4625980d4d (diff) | |
download | rneovim-4fb48c5654d9ffbffbdcdd80d0498b1ea3c8e68b.tar.gz rneovim-4fb48c5654d9ffbffbdcdd80d0498b1ea3c8e68b.tar.bz2 rneovim-4fb48c5654d9ffbffbdcdd80d0498b1ea3c8e68b.zip |
feat(server): set $NVIM, unset $NVIM_LISTEN_ADDRESS #11009
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
Diffstat (limited to 'src/nvim/msgpack_rpc/server.c')
-rw-r--r-- | src/nvim/msgpack_rpc/server.c | 49 |
1 files changed, 21 insertions, 28 deletions
diff --git a/src/nvim/msgpack_rpc/server.c b/src/nvim/msgpack_rpc/server.c index e954e4b3a3..f15ce82917 100644 --- a/src/nvim/msgpack_rpc/server.c +++ b/src/nvim/msgpack_rpc/server.c @@ -22,7 +22,8 @@ #include "nvim/vim.h" #define MAX_CONNECTIONS 32 -#define LISTEN_ADDRESS_ENV_VAR "NVIM_LISTEN_ADDRESS" +#define ENV_LISTEN "NVIM_LISTEN_ADDRESS" // deprecated +#define ENV_NVIM "NVIM" static garray_T watchers = GA_EMPTY_INIT_VALUE; @@ -35,20 +36,24 @@ bool server_init(const char *listen_addr) { ga_init(&watchers, sizeof(SocketWatcher *), 1); - // $NVIM_LISTEN_ADDRESS - const char *env_addr = os_getenv(LISTEN_ADDRESS_ENV_VAR); - int rv = listen_addr == NULL ? 1 : server_start(listen_addr); + // $NVIM_LISTEN_ADDRESS (deprecated) + if (!listen_addr && os_env_exists(ENV_LISTEN)) { + listen_addr = os_getenv(ENV_LISTEN); + } + int rv = listen_addr ? server_start(listen_addr) : 1; if (0 != rv) { - rv = env_addr == NULL ? 1 : server_start(env_addr); - if (0 != rv) { - listen_addr = server_address_new(); - if (listen_addr == NULL) { - return false; - } - rv = server_start(listen_addr); - xfree((char *)listen_addr); + listen_addr = server_address_new(); + if (!listen_addr) { + return false; } + rv = server_start(listen_addr); + xfree((char *)listen_addr); + } + + if (os_env_exists(ENV_LISTEN)) { + // Unset $NVIM_LISTEN_ADDRESS, it's a liability hereafter. + os_unsetenv(ENV_LISTEN); } return rv == 0; @@ -60,8 +65,8 @@ static void close_socket_watcher(SocketWatcher **watcher) socket_watcher_close(*watcher, free_server); } -/// Set v:servername to the first server in the server list, or unset it if no -/// servers are known. +/// Sets the "primary address" (v:servername and $NVIM) to the first server in +/// the server list, or unsets if no servers are known. static void set_vservername(garray_T *srvs) { char *default_server = (srvs->ga_len > 0) @@ -156,12 +161,6 @@ int server_start(const char *endpoint) return result; } - // Update $NVIM_LISTEN_ADDRESS, if not set. - const char *listen_address = os_getenv(LISTEN_ADDRESS_ENV_VAR); - if (listen_address == NULL) { - os_setenv(LISTEN_ADDRESS_ENV_VAR, watcher->addr, 1); - } - // Add the watcher to the list. ga_grow(&watchers, 1); ((SocketWatcher **)watchers.ga_data)[watchers.ga_len++] = watcher; @@ -200,12 +199,6 @@ bool server_stop(char *endpoint) return false; } - // Unset $NVIM_LISTEN_ADDRESS if it is the stopped address. - const char *listen_address = os_getenv(LISTEN_ADDRESS_ENV_VAR); - if (listen_address && STRCMP(addr, listen_address) == 0) { - os_unsetenv(LISTEN_ADDRESS_ENV_VAR); - } - socket_watcher_close(watcher, free_server); // Remove this server from the list by swapping it with the last item. @@ -215,8 +208,8 @@ bool server_stop(char *endpoint) } watchers.ga_len--; - // If v:servername is the stopped address, re-initialize it. - if (STRCMP(addr, get_vim_var_str(VV_SEND_SERVER)) == 0) { + // Bump v:servername to the next available server, if any. + if (strequal(addr, (char *)get_vim_var_str(VV_SEND_SERVER))) { set_vservername(&watchers); } |