summaryrefslogtreecommitdiff
path: root/src/lib/ecore_con
diff options
context:
space:
mode:
authorCarsten Haitzler (Rasterman) <raster@rasterman.com>2017-12-20 21:10:53 +0900
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>2017-12-20 21:10:53 +0900
commitb22b2ded1d72e63f7e3c3be425e973e6d8d3fb6c (patch)
tree6b784aad9e752373c43db323560446d17ecb02ff /src/lib/ecore_con
parent9c88bc4933560c74fd97a1cccc29fe6542f71755 (diff)
ecore_con: bug workaround SO_REUSEADDR and EADDRINUSE from bind (fix)
what i'm seeing is this with local unix sockets: 1. server process not cleanly shut down (kill -9 for example). 2. run server process again and bind fails due to EADDRINUSE 3. we ARE doing setsockopt() with SO_REUSEADDR set to 1 ... this just makes no sense because setsockopt() SHOULD allow use to re-use... the previous efreetd process for example is gone. no such process, yet socket is not re-usable. this should just not happen due to SO_REUSEADDR, but it does. this has nasty consequences like efreetd maybe never running because of stale sockets. this should never have happened, but it does. odd. so a hacky workaround: 1. try bind. 2. if bind fails with EADDRINUSE and its a socket path AND pd->unlink_before_bind is NOT set... then try a connect to the socket. 3. if connect succeeds then fail as normal (close socket and error on bind'ing) if connect fails then we have a stale socket, so unlink it forcibly. create the socket again and try bind again. hacky but... fixes the core issue. @fix
Diffstat (limited to '')
-rw-r--r--src/lib/ecore_con/efl_net_server_unix.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/src/lib/ecore_con/efl_net_server_unix.c b/src/lib/ecore_con/efl_net_server_unix.c
index b1a1d2d158..65f2b255e1 100644
--- a/src/lib/ecore_con/efl_net_server_unix.c
+++ b/src/lib/ecore_con/efl_net_server_unix.c
@@ -50,7 +50,7 @@ _efl_net_server_unix_bind(Eo *o, Efl_Net_Server_Unix_Data *pd)
50 const char *address = efl_net_server_address_get(o); 50 const char *address = efl_net_server_address_get(o);
51 struct sockaddr_un addr = { .sun_family = AF_UNIX }; 51 struct sockaddr_un addr = { .sun_family = AF_UNIX };
52 socklen_t addrlen; 52 socklen_t addrlen;
53 SOCKET fd; 53 SOCKET fd = INVALID_SOCKET;
54 Eina_Error err = 0; 54 Eina_Error err = 0;
55 int r; 55 int r;
56 56
@@ -108,6 +108,17 @@ _efl_net_server_unix_bind(Eo *o, Efl_Net_Server_Unix_Data *pd)
108 if ((err == EADDRINUSE) && (pd->unlink_before_bind) && (addr.sun_path[0] != '\0')) 108 if ((err == EADDRINUSE) && (pd->unlink_before_bind) && (addr.sun_path[0] != '\0'))
109 { 109 {
110 closesocket(fd); 110 closesocket(fd);
111 fd = INVALID_SOCKET;
112 err = 0;
113 continue;
114 }
115 if ((err == EADDRINUSE) && (addr.sun_path[0] != '\0') &&
116 (connect(fd, (struct sockaddr *)&addr, addrlen) != 0))
117 {
118 DBG("bind(" SOCKET_FMT ", %s): failed with EADDRINUSE but connect also failed, so unlink socket file and try again", fd, address);
119 closesocket(fd);
120 unlink(addr.sun_path);
121 fd = INVALID_SOCKET;
111 err = 0; 122 err = 0;
112 continue; 123 continue;
113 } 124 }
@@ -118,6 +129,7 @@ _efl_net_server_unix_bind(Eo *o, Efl_Net_Server_Unix_Data *pd)
118 } 129 }
119 while (pd->unlink_before_bind); 130 while (pd->unlink_before_bind);
120 131
132 if (fd == INVALID_SOCKET) goto error;
121 efl_loop_fd_set(o, fd); 133 efl_loop_fd_set(o, fd);
122 134
123 r = listen(fd, 0); 135 r = listen(fd, 0);