10000 Helper for setting TCP_USER_TIMEOUT socket option by zuiderkwast · Pull Request #1188 · redis/hiredis · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Helper for setting TCP_USER_TIMEOUT socket option #1188

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 32 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ REDIS_OPTIONS_SET_PRIVDATA(&opt, myPrivData, myPrivDataDtor);
opt->options |= REDIS_OPT_PREFER_IPV4;
```

If a connection is lost, `int redisReconnect(redisContext *c)` can be used to restore the connection using the same endpoint and options as the given context.

### Configurable redisOptions flags

There are several flags you may set in the `redisOptions` struct to change default behavior. You can specify the flags via the `redisOptions->options` member.
Expand All @@ -138,6 +140,36 @@ There are several flags you may set in the `redisOptions` struct to change defau

*Note: A `redisContext` is not thread-safe.*

### Other configuration using socket options

The following socket options are applied directly to the underlying socket.
The values are not stored in the `redisContext`, so they are not automatically applied when reconnecting using `redisReconnect()`.
These functions return `REDIS_OK` on success.
On failure, `REDIS_ERR` is returned and the underlying connection is closed.

To configure these for an asyncronous context (see *Asynchronous API* below), use `ac->c` to get the redisContext out of an asyncRedisContext.

```C
int redisEnableKeepAlive(redisContext *c);
int redisEnableKeepAliveWithInterval(redisContext *c, int interval);
```

Enables TCP keepalive by setting the following socket options (with some variations depending on OS):

* `SO_KEEPALIVE`;
* `TCP_KEEPALIVE` or `TCP_KEEPIDLE`, value configurable using the `interval` parameter, default 15 seconds;
* `TCP_KEEPINTVL` set to 1/3 of `interval`;
* `TCP_KEEPCNT` set to 3.

```C
int redisSetTcpUserTimeout(redisContext *c, unsigned int timeout);
```

Set the `TCP_USER_TIMEOUT` Linux-specific socket option which is as described in the `tcp` man page:

> When the value is greater than 0, it specifies the maximum amount of time in milliseconds that trans mitted data may remain unacknowledged before TCP will forcibly close the corresponding connection and return ETIMEDOUT to the application.
> If the option value is specified as 0, TCP will use the system default.

### Sending commands

There are several ways to issue commands to Redis. The first that will be introduced is
Expand Down Expand Up @@ -451,7 +483,6 @@ void appOnDisconnect(redisAsyncContext *c, int status)
}
```


### Sending commands and their callbacks

In an asynchronous context, commands are automatically pipelined due to the nature of an event loop.
Expand Down
5 changes: 5 additions & 0 deletions hiredis.c
Original file line number Diff line number Diff line change
Expand Up @@ -953,6 +953,11 @@ int redisEnableKeepAlive(redisContext *c) {
return redisKeepAlive(c, REDIS_KEEPALIVE_INTERVAL);
}

/* Set the socket option TCP_USER_TIMEOUT. */
int redisSetTcpUserTimeout(redisContext *c, unsigned int timeout) {
return redisContextSetTcpUserTimeout(c, timeout);
}

/* Set a user provided RESP3 PUSH handler and return any old one set. */
redisPushFn *redisSetPushCallback(redisContext *c, redisPushFn *fn) {
redisPushFn *old = c->push_cb;
Expand Down
1 change: 1 addition & 0 deletions hiredis.h
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,7 @@ redisPushFn *redisSetPushCallback(redisContext *c, redisPushFn *fn);
int redisSetTimeout(redisContext *c, const struct timeval tv);
int redisEnableKeepAlive(redisContext *c);
int redisEnableKeepAliveWithInterval(redisContext *c, int interval);
int redisSetTcpUserTimeout(redisContext *c, unsigned int timeout);
void redisFree(redisContext *c);
redisFD redisFreeKeepFd(redisContext *c);
int redisBufferRead(redisContext *c);
Expand Down
16 changes: 16 additions & 0 deletions net.c
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,22 @@ int redisSetTcpNoDelay(redisContext *c) {
return REDIS_OK;
}

int redisContextSetTcpUserTimeout(redisContext *c, unsigned int timeout) {
int res;
#ifdef TCP_USER_TIMEOUT
res = setsockopt(c->fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &timeout, sizeof(timeout));
#else
res = -1;
(void)timeout;
#endif
if (res == -1); {
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(TCP_USER_TIMEOUT)");
redisNetClose(c);
return REDIS_ERR;
}
return REDIS_OK;
}

#define __MAX_MSEC (((LONG_MAX) - 999) / 1000)

static int redisContextTimeoutMsec(redisContext *c, long *result)
Expand Down
1 change: 1 addition & 0 deletions net.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,6 @@ int redisKeepAlive(redisContext *c, int interval);
int redisCheckConnectDone(redisContext *c, int *completed);

int redisSetTcpNoDelay(redisContext *c);
int redisContextSetTcpUserTimeout(redisContext *c, unsigned int timeout);

#endif
0