mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
server: Refactor to ensure server handles are always properly closed
If the server fails to start(due to used address for example), the `server_start` function was freeing the handle memory before it was properly removed from libuv event loop queue. Fix that by replacing the `free(server)` call by `uv_close` call, which will take care of freeing the server on the next event loop iteration. Also replace `EMSG` calls by `ELOG`/`WLOG`.
This commit is contained in:
parent
d4f032a133
commit
5322333b47
@ -11,7 +11,7 @@
|
|||||||
#include "nvim/ascii.h"
|
#include "nvim/ascii.h"
|
||||||
#include "nvim/vim.h"
|
#include "nvim/vim.h"
|
||||||
#include "nvim/memory.h"
|
#include "nvim/memory.h"
|
||||||
#include "nvim/message.h"
|
#include "nvim/log.h"
|
||||||
#include "nvim/tempfile.h"
|
#include "nvim/tempfile.h"
|
||||||
#include "nvim/map.h"
|
#include "nvim/map.h"
|
||||||
#include "nvim/path.h"
|
#include "nvim/path.h"
|
||||||
@ -102,12 +102,12 @@ int server_start(const char *endpoint)
|
|||||||
if (xstrlcpy(addr, endpoint, sizeof(addr)) >= sizeof(addr)) {
|
if (xstrlcpy(addr, endpoint, sizeof(addr)) >= sizeof(addr)) {
|
||||||
// TODO(aktau): since this is not what the user wanted, perhaps we
|
// TODO(aktau): since this is not what the user wanted, perhaps we
|
||||||
// should return an error here
|
// should return an error here
|
||||||
EMSG2("Address was too long, truncated to %s", addr);
|
WLOG("Address was too long, truncated to %s", addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the server already exists
|
// Check if the server already exists
|
||||||
if (pmap_has(cstr_t)(servers, addr)) {
|
if (pmap_has(cstr_t)(servers, addr)) {
|
||||||
EMSG2("Already listening on %s", addr);
|
ELOG("Already listening on %s", addr);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,38 +152,30 @@ int server_start(const char *endpoint)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int result;
|
int result;
|
||||||
|
uv_stream_t *stream = NULL;
|
||||||
|
|
||||||
if (server_type == kServerTypeTcp) {
|
if (server_type == kServerTypeTcp) {
|
||||||
// Listen on tcp address/port
|
// Listen on tcp address/port
|
||||||
uv_tcp_init(uv_default_loop(), &server->socket.tcp.handle);
|
uv_tcp_init(uv_default_loop(), &server->socket.tcp.handle);
|
||||||
server->socket.tcp.handle.data = server;
|
|
||||||
result = uv_tcp_bind(&server->socket.tcp.handle,
|
result = uv_tcp_bind(&server->socket.tcp.handle,
|
||||||
(const struct sockaddr *)&server->socket.tcp.addr,
|
(const struct sockaddr *)&server->socket.tcp.addr,
|
||||||
0);
|
0);
|
||||||
if (result == 0) {
|
stream = (uv_stream_t *)&server->socket.tcp.handle;
|
||||||
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 {
|
} else {
|
||||||
// Listen on named pipe or unix socket
|
// Listen on named pipe or unix socket
|
||||||
xstrlcpy(server->socket.pipe.addr, addr, sizeof(server->socket.pipe.addr));
|
xstrlcpy(server->socket.pipe.addr, addr, sizeof(server->socket.pipe.addr));
|
||||||
uv_pipe_init(uv_default_loop(), &server->socket.pipe.handle, 0);
|
uv_pipe_init(uv_default_loop(), &server->socket.pipe.handle, 0);
|
||||||
server->socket.pipe.handle.data = server;
|
|
||||||
result = uv_pipe_bind(&server->socket.pipe.handle,
|
result = uv_pipe_bind(&server->socket.pipe.handle,
|
||||||
server->socket.pipe.addr);
|
server->socket.pipe.addr);
|
||||||
if (result == 0) {
|
stream = (uv_stream_t *)&server->socket.pipe.handle;
|
||||||
result = uv_listen((uv_stream_t *)&server->socket.pipe.handle,
|
}
|
||||||
MAX_CONNECTIONS,
|
|
||||||
connection_cb);
|
|
||||||
|
|
||||||
if (result) {
|
stream->data = server;
|
||||||
uv_close((uv_handle_t *)&server->socket.pipe.handle, free_server);
|
|
||||||
}
|
if (result == 0) {
|
||||||
}
|
result = uv_listen((uv_stream_t *)&server->socket.tcp.handle,
|
||||||
|
MAX_CONNECTIONS,
|
||||||
|
connection_cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(result <= 0); // libuv should have returned -errno or zero.
|
assert(result <= 0); // libuv should have returned -errno or zero.
|
||||||
@ -196,13 +188,12 @@ int server_start(const char *endpoint)
|
|||||||
result = -ENOENT;
|
result = -ENOENT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EMSG2("Failed to start server: %s", uv_strerror(result));
|
uv_close((uv_handle_t *)stream, free_server);
|
||||||
free(server);
|
ELOG("Failed to start server: %s", uv_strerror(result));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
server->type = server_type;
|
server->type = server_type;
|
||||||
|
|
||||||
// Add the server to the hash table
|
// Add the server to the hash table
|
||||||
pmap_put(cstr_t)(servers, addr, server);
|
pmap_put(cstr_t)(servers, addr, server);
|
||||||
|
|
||||||
@ -221,7 +212,7 @@ void server_stop(char *endpoint)
|
|||||||
xstrlcpy(addr, endpoint, sizeof(addr));
|
xstrlcpy(addr, endpoint, sizeof(addr));
|
||||||
|
|
||||||
if ((server = pmap_get(cstr_t)(servers, addr)) == NULL) {
|
if ((server = pmap_get(cstr_t)(servers, addr)) == NULL) {
|
||||||
EMSG2("Not listening on %s", addr);
|
ELOG("Not listening on %s", addr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,7 +246,7 @@ static void connection_cb(uv_stream_t *server, int status)
|
|||||||
result = uv_accept(server, client);
|
result = uv_accept(server, client);
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
EMSG2("Failed to accept connection: %s", uv_strerror(result));
|
ELOG("Failed to accept connection: %s", uv_strerror(result));
|
||||||
uv_close((uv_handle_t *)client, free_client);
|
uv_close((uv_handle_t *)client, free_client);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user