diff --git a/src/anet.c b/src/anet.c index 91ab94efd..b32dc6d46 100644 --- a/src/anet.c +++ b/src/anet.c @@ -476,7 +476,7 @@ static int anetV6Only(char *err, int s) { return ANET_OK; } -static int _anetTcpServer(char *err, int port, char *bindaddr, int af, int backlog, int fReusePort) +static int _anetTcpServer(char *err, int port, char *bindaddr, int af, int backlog, int fReusePort, int fFirstListen) { int s = -1, rv; char _port[6]; /* strlen("65535") */ @@ -498,8 +498,12 @@ static int _anetTcpServer(char *err, int port, char *bindaddr, int af, int backl if (af == AF_INET6 && anetV6Only(err,s) == ANET_ERR) goto error; if (anetSetReuseAddr(err,s) == ANET_ERR) goto error; - if (fReusePort && anetSetReusePort(err,s) == ANET_ERR) goto error; - if (anetListen(err,s,p->ai_addr,p->ai_addrlen,backlog) == ANET_ERR) s = ANET_ERR; + if (fReusePort && !fFirstListen && anetSetReusePort(err,s) == ANET_ERR) goto error; + if (anetListen(err,s,p->ai_addr,p->ai_addrlen,backlog) == ANET_ERR) { + s = ANET_ERR; + goto end; + } + if (fReusePort && fFirstListen && anetSetReusePort(err,s) == ANET_ERR) goto error; goto end; } if (p == NULL) { @@ -515,14 +519,14 @@ end: return s; } -int anetTcpServer(char *err, int port, char *bindaddr, int backlog, int fReusePort) +int anetTcpServer(char *err, int port, char *bindaddr, int backlog, int fReusePort, int fFirstListen) { - return _anetTcpServer(err, port, bindaddr, AF_INET, backlog, fReusePort); + return _anetTcpServer(err, port, bindaddr, AF_INET, backlog, fReusePort, fFirstListen); } -int anetTcp6Server(char *err, int port, char *bindaddr, int backlog, int fReusePort) +int anetTcp6Server(char *err, int port, char *bindaddr, int backlog, int fReusePort, int fFirstListen) { - return _anetTcpServer(err, port, bindaddr, AF_INET6, backlog, fReusePort); + return _anetTcpServer(err, port, bindaddr, AF_INET6, backlog, fReusePort, fFirstListen); } int anetUnixServer(char *err, char *path, mode_t perm, int backlog) diff --git a/src/anet.h b/src/anet.h index 44c57b4cd..06791ee1c 100644 --- a/src/anet.h +++ b/src/anet.h @@ -62,8 +62,8 @@ int anetUnixNonBlockConnect(char *err, char *path); int anetRead(int fd, char *buf, int count); int anetResolve(char *err, char *host, char *ipbuf, size_t ipbuf_len); int anetResolveIP(char *err, char *host, char *ipbuf, size_t ipbuf_len); -int anetTcpServer(char *err, int port, char *bindaddr, int backlog, int fReusePort); -int anetTcp6Server(char *err, int port, char *bindaddr, int backlog, int fReusePort); +int anetTcpServer(char *err, int port, char *bindaddr, int backlog, int fReusePort, int fFirstListen); +int anetTcp6Server(char *err, int port, char *bindaddr, int backlog, int fReusePort, int fFirstListen); int anetUnixServer(char *err, char *path, mode_t perm, int backlog); int anetTcpAccept(char *err, int serversock, char *ip, size_t ip_len, int *port); int anetUnixAccept(char *err, int serversock); diff --git a/src/cluster.cpp b/src/cluster.cpp index 619ce3b3a..6ba5cfef7 100644 --- a/src/cluster.cpp +++ b/src/cluster.cpp @@ -499,7 +499,7 @@ void clusterInit(void) { } if (listenToPort(g_pserver->port+CLUSTER_PORT_INCR, - g_pserver->cfd,&g_pserver->cfd_count, 0 /*fReusePort*/) == C_ERR) + g_pserver->cfd,&g_pserver->cfd_count, 0 /*fReusePort*/, 0 /*fFirstListen*/) == C_ERR) { exit(1); } else { diff --git a/src/server.cpp b/src/server.cpp index 2db38dceb..d88a0d9e4 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -2704,7 +2704,7 @@ void checkTcpBacklogSettings(void) { * impossible to bind, or no bind addresses were specified in the server * configuration but the function is not able to bind * for at least * one of the IPv4 or IPv6 protocols. */ -int listenToPort(int port, int *fds, int *count, int fReusePort) { +int listenToPort(int port, int *fds, int *count, int fReusePort, int fFirstListen) { int j; /* Force binding of 0.0.0.0 if no bind address is specified, always @@ -2716,7 +2716,7 @@ int listenToPort(int port, int *fds, int *count, int fReusePort) { /* Bind * for both IPv6 and IPv4, we enter here only if * g_pserver->bindaddr_count == 0. */ fds[*count] = anetTcp6Server(serverTL->neterr,port,NULL, - g_pserver->tcp_backlog, fReusePort); + g_pserver->tcp_backlog, fReusePort, fFirstListen); if (fds[*count] != ANET_ERR) { anetNonBlock(NULL,fds[*count]); (*count)++; @@ -2728,7 +2728,7 @@ int listenToPort(int port, int *fds, int *count, int fReusePort) { if (*count == 1 || unsupported) { /* Bind the IPv4 address as well. */ fds[*count] = anetTcpServer(serverTL->neterr,port,NULL, - g_pserver->tcp_backlog, fReusePort); + g_pserver->tcp_backlog, fReusePort, fFirstListen); if (fds[*count] != ANET_ERR) { anetNonBlock(NULL,fds[*count]); (*count)++; @@ -2744,11 +2744,11 @@ int listenToPort(int port, int *fds, int *count, int fReusePort) { } else if (strchr(g_pserver->bindaddr[j],':')) { /* Bind IPv6 address. */ fds[*count] = anetTcp6Server(serverTL->neterr,port,g_pserver->bindaddr[j], - g_pserver->tcp_backlog, fReusePort); + g_pserver->tcp_backlog, fReusePort, fFirstListen); } else { /* Bind IPv4 address. */ fds[*count] = anetTcpServer(serverTL->neterr,port,g_pserver->bindaddr[j], - g_pserver->tcp_backlog, fReusePort); + g_pserver->tcp_backlog, fReusePort, fFirstListen); } if (fds[*count] == ANET_ERR) { serverLog(LL_WARNING, @@ -2810,7 +2810,7 @@ static void initNetworkingThread(int iel, int fReusePort) if (fReusePort || (iel == IDX_EVENT_LOOP_MAIN)) { if (g_pserver->port != 0 && - listenToPort(g_pserver->port,g_pserver->rgthreadvar[iel].ipfd,&g_pserver->rgthreadvar[iel].ipfd_count, fReusePort) == C_ERR) + listenToPort(g_pserver->port,g_pserver->rgthreadvar[iel].ipfd,&g_pserver->rgthreadvar[iel].ipfd_count, fReusePort, (iel == IDX_EVENT_LOOP_MAIN)) == C_ERR) exit(1); } else diff --git a/src/server.h b/src/server.h index 6a2bda9fa..4e7dab351 100644 --- a/src/server.h +++ b/src/server.h @@ -2014,7 +2014,7 @@ const char *getClientTypeName(int cclass); void flushSlavesOutputBuffers(void); void disconnectSlaves(void); void disconnectSlavesExcept(unsigned char *uuid); -int listenToPort(int port, int *fds, int *count, int fReusePort); +int listenToPort(int port, int *fds, int *count, int fReusePort, int fFirstListen); void pauseClients(mstime_t duration); int clientsArePaused(void); int processEventsWhileBlocked(int iel);