diff options
-rw-r--r-- | src/anet.c | 24 | ||||
-rw-r--r-- | src/cluster.c | 1 | ||||
-rw-r--r-- | src/config.h | 5 | ||||
-rw-r--r-- | src/networking.c | 4 |
4 files changed, 29 insertions, 5 deletions
diff --git a/src/anet.c b/src/anet.c index 381dda375..f4f3a98bf 100644 --- a/src/anet.c +++ b/src/anet.c @@ -47,6 +47,7 @@ #include <stdio.h> #include "anet.h" +#include "config.h" static void anetSetError(char *err, const char *fmt, ...) { @@ -491,18 +492,39 @@ int anetUnixServer(char *err, char *path, mode_t perm, int backlog) return s; } +/* Accept a connection and also make sure the socket is non-blocking, and CLOEXEC. + * returns the new socket FD, or -1 on error. */ static int anetGenericAccept(char *err, int s, struct sockaddr *sa, socklen_t *len) { int fd; do { + /* Use the accept4() call on linux to simultaneously accept and + * set a socket as non-blocking. */ +#ifdef HAVE_ACCEPT4 + fd = accept4(s, sa, len, SOCK_NONBLOCK | SOCK_CLOEXEC); +#else fd = accept(s,sa,len); +#endif } while(fd == -1 && errno == EINTR); if (fd == -1) { anetSetError(err, "accept: %s", strerror(errno)); return ANET_ERR; } +#ifndef HAVE_ACCEPT4 + if (anetCloexec(fd) == -1) { + anetSetError(err, "anetCloexec: %s", strerror(errno)); + close(fd); + return ANET_ERR; + } + if (anetNonBlock(err, fd) != ANET_OK) { + close(fd); + return ANET_ERR; + } +#endif return fd; } +/* Accept a connection and also make sure the socket is non-blocking, and CLOEXEC. + * returns the new socket FD, or -1 on error. */ int anetTcpAccept(char *err, int s, char *ip, size_t ip_len, int *port) { int fd; struct sockaddr_storage sa; @@ -522,6 +544,8 @@ int anetTcpAccept(char *err, int s, char *ip, size_t ip_len, int *port) { return fd; } +/* Accept a connection and also make sure the socket is non-blocking, and CLOEXEC. + * returns the new socket FD, or -1 on error. */ int anetUnixAccept(char *err, int s) { int fd; struct sockaddr_un sa; diff --git a/src/cluster.c b/src/cluster.c index 12ea935d5..92601b001 100644 --- a/src/cluster.c +++ b/src/cluster.c @@ -735,7 +735,6 @@ void clusterAcceptHandler(aeEventLoop *el, int fd, void *privdata, int mask) { connClose(conn); return; } - connNonBlock(conn); connEnableTcpNoDelay(conn); /* Use non-blocking I/O for cluster messages. */ diff --git a/src/config.h b/src/config.h index 56c1ab6ae..af5209f89 100644 --- a/src/config.h +++ b/src/config.h @@ -78,6 +78,11 @@ #define HAVE_EPOLL 1 #endif +/* Test for accept4() */ +#ifdef __linux__ +#define HAVE_ACCEPT4 1 +#endif + #if (defined(__APPLE__) && defined(MAC_OS_X_VERSION_10_6)) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined (__NetBSD__) #define HAVE_KQUEUE 1 #endif diff --git a/src/networking.c b/src/networking.c index 805f3f0e9..8e16b7575 100644 --- a/src/networking.c +++ b/src/networking.c @@ -115,7 +115,6 @@ client *createClient(connection *conn) { * in the context of a client. When commands are executed in other * contexts (for instance a Lua script) we need a non connected client. */ if (conn) { - connNonBlock(conn); connEnableTcpNoDelay(conn); if (server.tcpkeepalive) connKeepAlive(conn,server.tcpkeepalive); @@ -1122,7 +1121,6 @@ void acceptTcpHandler(aeEventLoop *el, int fd, void *privdata, int mask) { "Accepting client connection: %s", server.neterr); return; } - anetCloexec(cfd); serverLog(LL_VERBOSE,"Accepted %s:%d", cip, cport); acceptCommonHandler(connCreateAcceptedSocket(cfd),0,cip); } @@ -1143,7 +1141,6 @@ void acceptTLSHandler(aeEventLoop *el, int fd, void *privdata, int mask) { "Accepting client connection: %s", server.neterr); return; } - anetCloexec(cfd); serverLog(LL_VERBOSE,"Accepted %s:%d", cip, cport); acceptCommonHandler(connCreateAcceptedTLS(cfd, server.tls_auth_clients),0,cip); } @@ -1163,7 +1160,6 @@ void acceptUnixHandler(aeEventLoop *el, int fd, void *privdata, int mask) { "Accepting client connection: %s", server.neterr); return; } - anetCloexec(cfd); serverLog(LL_VERBOSE,"Accepted connection to %s", server.unixsocket); acceptCommonHandler(connCreateAcceptedSocket(cfd),CLIENT_UNIX_SOCKET,NULL); } |