From 10eacf2873707db8468d86f52c78414041c5e7d3 Mon Sep 17 00:00:00 2001 From: Denis Osvald Date: Tue, 3 Jan 2017 02:06:37 +0800 Subject: [PATCH] server: check listen(2) return value The `listen` call can fail with EADDRINUSE after bind() succeeds, for example because another process called listen on that port in the meantime, or under some circumstances with IPv6-mapped-IPv4. This was causing EINVAL on accept, with an infinite loop in case of libuv. A reproducible example was to run nc -l -p 5555 ( OpenBSD netcat (Debian patchlevel 1)) before starting test-server Signed-off-by: Denis Osvald --- lib/server.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/server.c b/lib/server.c index f244faed..933914a5 100644 --- a/lib/server.c +++ b/lib/server.c @@ -132,7 +132,15 @@ lws_context_init_server(struct lws_context_creation_info *info, vhost->lserv_wsi = wsi; #if LWS_POSIX - listen(wsi->sock, LWS_SOMAXCONN); + n = listen(wsi->sock, LWS_SOMAXCONN); + if (n < 0) { + lwsl_err("listen failed with error %d\n", LWS_ERRNO); + vhost->lserv_wsi = NULL; + vhost->context->count_wsi_allocated--; + remove_wsi_socket_from_fds(wsi); + vhost->context->pt[m].wsi_listening = NULL; + goto bail; + } } /* for each thread able to independently listen */ #else mbed3_tcp_stream_bind(wsi->sock, info->port, wsi);