summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/anet.c24
-rw-r--r--src/cluster.c1
-rw-r--r--src/config.h5
-rw-r--r--src/networking.c4
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);
}