aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Prager <splinterofchaos@gmail.com>2014-10-16 10:02:13 -0400
committerScott Prager <splinterofchaos@gmail.com>2014-10-17 12:26:10 -0400
commit792882e9e415e7dfb26e0778d760003a7d4747e1 (patch)
tree7dfbaf2d7a24212435b9971aa7451dd096628607
parent0a2d9fa8c88b6e263b9baa9b639c23321272f9bf (diff)
downloadrneovim-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.c61
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`.