diff --git a/hiredis.c b/hiredis.c index 739ce2a24..c5367d395 100644 --- a/hiredis.c +++ b/hiredis.c @@ -835,6 +835,9 @@ redisContext *redisConnectWithOptions(const redisOptions *options) { if (options->options & REDIS_OPT_PREFER_IPV6) { c->flags |= REDIS_PREFER_IPV6; } + if (options->options & REDIS_OPT_SET_SOCK_CLOEXEC) { + c->flags |= REDIS_OPT_SET_SOCK_CLOEXEC; + } /* Set any user supplied RESP3 PUSH handler or use freeReplyObject * as a default unless specifically flagged that we don't want one. */ diff --git a/hiredis.h b/hiredis.h index e3aa5aa9e..302a7ac4c 100644 --- a/hiredis.h +++ b/hiredis.h @@ -165,6 +165,7 @@ struct redisSsl; #define REDIS_OPT_PREFER_IPV4 0x20 /* Prefer IPv4 in DNS lookups. */ #define REDIS_OPT_PREFER_IPV6 0x40 /* Prefer IPv6 in DNS lookups. */ #define REDIS_OPT_PREFER_IP_UNSPEC (REDIS_OPT_PREFER_IPV4 | REDIS_OPT_PREFER_IPV6) +#define REDIS_OPT_SET_SOCK_CLOEXEC 0x80 /* Set SOCK_CLOEXEC on socket file descriptor. */ /* In Unix systems a file descriptor is a regular signed int, with -1 * representing an invalid descriptor. In Windows it is a SOCKET diff --git a/net.c b/net.c index b514babaf..3973e95fa 100644 --- a/net.c +++ b/net.c @@ -122,11 +122,20 @@ static int redisSetReuseAddr(redisContext *c) { static int redisCreateSocket(redisContext *c, int type) { redisFD s; - if ((s = socket(type, SOCK_STREAM, 0)) == REDIS_INVALID_FD) { - __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); + int flags = SOCK_STREAM; + +#ifdef SOCK_CLOEXEC + if (c->flags & REDIS_OPT_SET_SOCK_CLOEXEC) { + flags |= SOCK_CLOEXEC; + } +#endif + + if ((s = socket(type, flags, 0)) == REDIS_INVALID_FD) { + __redisSetErrorFromErrno(c, REDIS_ERR_IO, NULL); return REDIS_ERR; } c->fd = s; + if (type == AF_INET) { if (redisSetReuseAddr(c) == REDIS_ERR) { return REDIS_ERR; @@ -512,11 +521,21 @@ static int _redisContextConnectTcp(redisContext *c, const char *addr, int port, return REDIS_ERR; } for (p = servinfo; p != NULL; p = p->ai_next) { -addrretry: - if ((s = socket(p->ai_family,p->ai_socktype,p->ai_protocol)) == REDIS_INVALID_FD) +addrretry: { + int sock_type = p->ai_socktype; + +#ifdef SOCK_CLOEXEC + if (c->flags & REDIS_OPT_SET_SOCK_CLOEXEC) { + sock_type |= SOCK_CLOEXEC; + } +#endif + + if ((s = socket(p->ai_family, sock_type, p->ai_protocol)) == REDIS_INVALID_FD) continue; +} c->fd = s; + if (redisSetBlocking(c,0) != REDIS_OK) goto error; if (c->tcp.source_addr) {