diff options
author | Josh Rahm <joshuarahm@gmail.com> | 2024-11-19 22:57:13 +0000 |
---|---|---|
committer | Josh Rahm <joshuarahm@gmail.com> | 2024-11-19 22:57:13 +0000 |
commit | 9be89f131f87608f224f0ee06d199fcd09d32176 (patch) | |
tree | 11022dcfa9e08cb4ac5581b16734196128688d48 /src/nvim/msgpack_rpc/server.c | |
parent | ff7ed8f586589d620a806c3758fac4a47a8e7e15 (diff) | |
parent | 88085c2e80a7e3ac29aabb6b5420377eed99b8b6 (diff) | |
download | rneovim-9be89f131f87608f224f0ee06d199fcd09d32176.tar.gz rneovim-9be89f131f87608f224f0ee06d199fcd09d32176.tar.bz2 rneovim-9be89f131f87608f224f0ee06d199fcd09d32176.zip |
Merge remote-tracking branch 'upstream/master' into mix_20240309
Diffstat (limited to 'src/nvim/msgpack_rpc/server.c')
-rw-r--r-- | src/nvim/msgpack_rpc/server.c | 67 |
1 files changed, 48 insertions, 19 deletions
diff --git a/src/nvim/msgpack_rpc/server.c b/src/nvim/msgpack_rpc/server.c index 56b03d67d0..462f8397f4 100644 --- a/src/nvim/msgpack_rpc/server.c +++ b/src/nvim/msgpack_rpc/server.c @@ -4,18 +4,21 @@ #include <string.h> #include <uv.h> +#include "nvim/ascii_defs.h" #include "nvim/channel.h" #include "nvim/eval.h" #include "nvim/event/defs.h" #include "nvim/event/socket.h" #include "nvim/garray.h" #include "nvim/garray_defs.h" +#include "nvim/globals.h" #include "nvim/log.h" #include "nvim/main.h" #include "nvim/memory.h" #include "nvim/msgpack_rpc/server.h" #include "nvim/os/os.h" #include "nvim/os/stdpaths_defs.h" +#include "nvim/types_defs.h" #define MAX_CONNECTIONS 32 #define ENV_LISTEN "NVIM_LISTEN_ADDRESS" // deprecated @@ -26,37 +29,61 @@ static garray_T watchers = GA_EMPTY_INIT_VALUE; # include "msgpack_rpc/server.c.generated.h" #endif -/// Initializes the module +/// Initializes resources, handles `--listen`, starts the primary server at v:servername. +/// +/// @returns true on success, false on fatal error (message stored in IObuff) bool server_init(const char *listen_addr) { + bool ok = true; + bool must_free = false; + TriState user_arg = kTrue; // User-provided --listen arg. ga_init(&watchers, sizeof(SocketWatcher *), 1); // $NVIM_LISTEN_ADDRESS (deprecated) - if (!listen_addr && os_env_exists(ENV_LISTEN)) { + if ((!listen_addr || listen_addr[0] == '\0') && os_env_exists(ENV_LISTEN)) { + user_arg = kFalse; // User-provided env var. listen_addr = os_getenv(ENV_LISTEN); } - int rv = listen_addr ? server_start(listen_addr) : 1; - if (0 != rv) { + if (!listen_addr || listen_addr[0] == '\0') { + user_arg = kNone; // Autogenerated server address. listen_addr = server_address_new(NULL); - if (!listen_addr) { - return false; - } - rv = server_start(listen_addr); - xfree((char *)listen_addr); + must_free = true; } - if (os_env_exists(ENV_LISTEN)) { - // Unset $NVIM_LISTEN_ADDRESS, it's a liability hereafter. - os_unsetenv(ENV_LISTEN); - } + int rv = server_start(listen_addr); - // TODO(justinmk): this is for logging_spec. Can remove this after nvim_log #7062 is merged. + // TODO(justinmk): this is for log_spec. Can remove this after nvim_log #7062 is merged. if (os_env_exists("__NVIM_TEST_LOG")) { ELOG("test log message"); } - return rv == 0; + if (must_free) { + xfree((char *)listen_addr); + } + + if (rv == 0 || user_arg == kNone) { + // The autogenerated servername can fail if the user has a broken $XDG_RUNTIME_DIR. #30282 + // But that is not fatal (startup will continue, logged in $NVIM_LOGFILE, empty v:servername). + goto end; + } + + (void)snprintf(IObuff, IOSIZE, + user_arg == + kTrue ? "Failed to --listen: %s: \"%s\"" + : "Failed $NVIM_LISTEN_ADDRESS: %s: \"%s\"", + rv < 0 ? os_strerror(rv) : (rv == 1 ? "empty address" : "?"), + listen_addr); + ok = false; + +end: + if (os_env_exists(ENV_LISTEN)) { + // Unset $NVIM_LISTEN_ADDRESS, it's a liability hereafter. It is "input only", it must not be + // leaked to child jobs or :terminal. + os_unsetenv(ENV_LISTEN); + } + + return ok; } /// Teardown a single server @@ -87,17 +114,19 @@ void server_teardown(void) /// - Windows: "\\.\pipe\<name>.<pid>.<counter>" /// - Other: "/tmp/nvim.user/xxx/<name>.<pid>.<counter>" char *server_address_new(const char *name) + FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_RET { static uint32_t count = 0; char fmt[ADDRESS_MAX_SIZE]; - const char *appname = get_appname(); #ifdef MSWIN + (void)get_appname(true); int r = snprintf(fmt, sizeof(fmt), "\\\\.\\pipe\\%s.%" PRIu64 ".%" PRIu32, - name ? name : appname, os_get_pid(), count++); + name ? name : NameBuff, os_get_pid(), count++); #else char *dir = stdpaths_get_xdg_var(kXDGRuntimeDir); + (void)get_appname(true); int r = snprintf(fmt, sizeof(fmt), "%s/%s.%" PRIu64 ".%" PRIu32, - dir, name ? name : appname, os_get_pid(), count++); + dir, name ? name : NameBuff, os_get_pid(), count++); xfree(dir); #endif if ((size_t)r >= sizeof(fmt)) { @@ -131,7 +160,7 @@ bool server_owns_pipe_address(const char *path) /// @returns 0: success, 1: validation error, 2: already listening, -errno: failed to bind/listen. int server_start(const char *addr) { - if (addr == NULL || addr[0] == '\0') { + if (addr == NULL || addr[0] == NUL) { WLOG("Empty or NULL address"); return 1; } |