Skip to content

Commit

Permalink
Use a windows specific keepalive function. (#1104)
Browse files Browse the repository at this point in the history
Use a windows specific keepalive function.

While it is possible to toggle `TCP_KEEPALIVE` in windows via
setsockopt, you have to use `WSAIoctl` to set the interval.

Since `WSAIoctl` can actually do all of this in one call (toggle the
option, and set the corresponding interval), just use that in Windows
and avoid the call to `setsockopt` alltogether.

Fixes: #1100
  • Loading branch information
michael-grunder authored Sep 3, 2022
1 parent fce8abc commit 61b5b29
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 0 deletions.
9 changes: 9 additions & 0 deletions net.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ int redisKeepAlive(redisContext *c, int interval) {
int val = 1;
redisFD fd = c->fd;

#ifndef _WIN32
if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) == -1){
__redisSetError(c,REDIS_ERR_OTHER,strerror(errno));
return REDIS_ERR;
Expand Down Expand Up @@ -201,7 +202,15 @@ int redisKeepAlive(redisContext *c, int interval) {
}
#endif
#endif
#else
int res;

res = win32_redisKeepAlive(fd, interval * 1000);
if (res != 0) {
__redisSetError(c, REDIS_ERR_OTHER, strerror(res));
return REDIS_ERR;
}
#endif
return REDIS_OK;
}

Expand Down
17 changes: 17 additions & 0 deletions sockcompat.c
Original file line number Diff line number Diff line change
Expand Up @@ -260,4 +260,21 @@ int win32_poll(struct pollfd *fds, nfds_t nfds, int timeout) {
_updateErrno(ret != SOCKET_ERROR);
return ret != SOCKET_ERROR ? ret : -1;
}

int win32_redisKeepAlive(SOCKET sockfd, int interval_ms) {
struct tcp_keepalive cfg;
DWORD bytes_in;
int res;

cfg.onoff = 1;
cfg.keepaliveinterval = interval_ms;
cfg.keepalivetime = interval_ms;

res = WSAIoctl(sockfd, SIO_KEEPALIVE_VALS, &cfg,
sizeof(struct tcp_keepalive), NULL, 0,
&bytes_in, NULL, NULL);

return res == 0 ? 0 : _wsaErrorToErrno(res);
}

#endif /* _WIN32 */
3 changes: 3 additions & 0 deletions sockcompat.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
#include <ws2tcpip.h>
#include <stddef.h>
#include <errno.h>
#include <Mstcpip.h>

#ifdef _MSC_VER
typedef long long ssize_t;
Expand All @@ -71,6 +72,8 @@ ssize_t win32_send(SOCKET sockfd, const void *buf, size_t len, int flags);
typedef ULONG nfds_t;
int win32_poll(struct pollfd *fds, nfds_t nfds, int timeout);

int win32_redisKeepAlive(SOCKET sockfd, int interval_ms);

#ifndef REDIS_SOCKCOMPAT_IMPLEMENTATION
#define getaddrinfo(node, service, hints, res) win32_getaddrinfo(node, service, hints, res)
#undef gai_strerror
Expand Down
11 changes: 11 additions & 0 deletions test.c
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,16 @@ static void test_append_formatted_commands(struct config config) {
disconnect(c, 0);
}

static void test_tcp_options(struct config cfg) {
redisContext *c;

c = do_connect(cfg);
test("We can enable TCP_KEEPALIVE: ");
test_cond(redisEnableKeepAlive(c) == REDIS_OK);

disconnect(c, 0);
}

static void test_reply_reader(void) {
redisReader *reader;
void *reply, *root;
Expand Down Expand Up @@ -2261,6 +2271,7 @@ int main(int argc, char **argv) {
test_blocking_io_errors(cfg);
test_invalid_timeout_errors(cfg);
test_append_formatted_commands(cfg);
test_tcp_options(cfg);
if (throughput) test_throughput(cfg);

printf("\nTesting against Unix socket connection (%s): ", cfg.unix_sock.path);
Expand Down

0 comments on commit 61b5b29

Please sign in to comment.