diff options
author | Scott Prager <splinterofchaos@gmail.com> | 2014-10-16 10:02:13 -0400 |
---|---|---|
committer | Scott Prager <splinterofchaos@gmail.com> | 2014-10-17 12:26:10 -0400 |
commit | 792882e9e415e7dfb26e0778d760003a7d4747e1 (patch) | |
tree | 7dfbaf2d7a24212435b9971aa7451dd096628607 | |
parent | 0a2d9fa8c88b6e263b9baa9b639c23321272f9bf (diff) | |
download | rneovim-792882e9e415e7dfb26e0778d760003a7d4747e1.tar.gz rneovim-792882e9e415e7dfb26e0778d760003a7d4747e1.tar.bz2 rneovim-792882e9e415e7dfb26e0778d760003a7d4747e1.zip |
server: Improve error reporting.
If we fail to bind to the server address, do not try and listen lest the
reported error always be "invalid argument".
Also, return whether or not we errored from server_init() in case we
want to respond differently in the future.
-rw-r--r-- | src/nvim/os/server.c | 61 |
1 files changed, 41 insertions, 20 deletions
diff --git a/src/nvim/os/server.c b/src/nvim/os/server.c index 66dd0ecd88..9f7f5b34da 100644 --- a/src/nvim/os/server.c +++ b/src/nvim/os/server.c @@ -1,3 +1,4 @@ +#include <assert.h> #include <stdlib.h> #include <string.h> #include <stdint.h> @@ -13,6 +14,7 @@ #include "nvim/message.h" #include "nvim/tempfile.h" #include "nvim/map.h" +#include "nvim/path.h" #define MAX_CONNECTIONS 32 #define ADDRESS_MAX_SIZE 256 @@ -48,7 +50,7 @@ static PMap(cstr_t) *servers = NULL; #endif /// Initializes the module -void server_init(void) +bool server_init(void) { servers = pmap_new(cstr_t)(); @@ -58,7 +60,7 @@ void server_init(void) free(listen_address); } - server_start((char *)os_getenv(LISTEN_ADDRESS_ENV_VAR)); + return server_start((char *)os_getenv(LISTEN_ADDRESS_ENV_VAR)) == 0; } /// Teardown the server module @@ -89,7 +91,10 @@ void server_teardown(void) /// @param endpoint Address of the server. Either a 'ip[:port]' string or an /// arbitrary identifier(trimmed to 256 bytes) for the unix socket or /// named pipe. -void server_start(char *endpoint) +/// @returns zero if successful, one on a regular error, and negative errno +/// on failure to bind or connect. +int server_start(const char *endpoint) + FUNC_ATTR_NONNULL_ALL { char addr[ADDRESS_MAX_SIZE]; @@ -103,7 +108,7 @@ void server_start(char *endpoint) // Check if the server already exists if (pmap_has(cstr_t)(servers, addr)) { EMSG2("Already listening on %s", addr); - return; + return 1; } ServerType server_type = kServerTypeTcp; @@ -151,40 +156,56 @@ void server_start(char *endpoint) // Listen on tcp address/port uv_tcp_init(uv_default_loop(), &server->socket.tcp.handle); server->socket.tcp.handle.data = server; - uv_tcp_bind(&server->socket.tcp.handle, + result = uv_tcp_bind(&server->socket.tcp.handle, (const struct sockaddr *)&server->socket.tcp.addr, 0); - result = uv_listen((uv_stream_t *)&server->socket.tcp.handle, - MAX_CONNECTIONS, - connection_cb); - if (result) { - uv_close((uv_handle_t *)&server->socket.tcp.handle, free_server); + if (result == 0) { + result = uv_listen((uv_stream_t *)&server->socket.tcp.handle, + MAX_CONNECTIONS, + connection_cb); + if (result) { + uv_close((uv_handle_t *)&server->socket.tcp.handle, free_server); + } } } else { // Listen on named pipe or unix socket xstrlcpy(server->socket.pipe.addr, addr, sizeof(server->socket.pipe.addr)); uv_pipe_init(uv_default_loop(), &server->socket.pipe.handle, 0); server->socket.pipe.handle.data = server; - uv_pipe_bind(&server->socket.pipe.handle, server->socket.pipe.addr); - result = uv_listen((uv_stream_t *)&server->socket.pipe.handle, - MAX_CONNECTIONS, - connection_cb); - - if (result) { - uv_close((uv_handle_t *)&server->socket.pipe.handle, free_server); + result = uv_pipe_bind(&server->socket.pipe.handle, + server->socket.pipe.addr); + if (result == 0) { + result = uv_listen((uv_stream_t *)&server->socket.pipe.handle, + MAX_CONNECTIONS, + connection_cb); + + if (result) { + uv_close((uv_handle_t *)&server->socket.pipe.handle, free_server); + } } } - if (result) { + assert(result <= 0); // libuv should have returned -errno or zero. + if (result < 0) { + if (result == -EACCES) { + // Libuv converts ENOENT to EACCES for Windows compatibility, but if + // the parent directory does not exist, ENOENT would be more accurate. + *path_tail((char_u *) addr) = NUL; + if (!os_file_exists((char_u *) addr)) { + result = -ENOENT; + } + } EMSG2("Failed to start server: %s", uv_strerror(result)); - return; + free(server); + return result; } - server->type = server_type; // Add the server to the hash table pmap_put(cstr_t)(servers, addr, server); + + return 0; } /// Stops listening on the address specified by `endpoint`. |