summaryrefslogtreecommitdiff
path: root/src/anet.c
diff options
context:
space:
mode:
authorOran Agra <oran@redislabs.com>2020-10-28 21:09:15 +0200
committerGitHub <noreply@github.com>2020-10-28 21:09:15 +0200
commit441bfa2dfb57e0dbfddad167bafa559b3f051b5b (patch)
treeb780b8fcbe464d81bbb37f3e01bb918030634103 /src/anet.c
parentd310beb4170ebbc8985ae120ee301f9213d33e39 (diff)
downloadredis-441bfa2dfb57e0dbfddad167bafa559b3f051b5b.tar.gz
Optionally (default) fail to start if requested bind address is not available (#7936)
Background: #3467 (redis 4.0.0), started ignoring ENOPROTOOPT, but did that only for the default bind (in case bind config wasn't explicitly set). #5598 (redis 5.0.3), added that for bind addresses explicitly set (following bug reports in Debian for redis 4.0.9 and 5.0.1), it also ignored a bunch of other errors like EPROTONOSUPPORT which was requested in #3894, and also added EADDRNOTAVAIL (wasn't clear why). This (ignoring EADDRNOTAVAIL) makes redis start successfully, even if a certain network interface isn't up yet , in which case we rather redis fail and will be re-tried when the NIC is up, see #7933. However, it turns out that when IPv6 is disabled (supported but unused), the error we're getting is EADDRNOTAVAIL. and in many systems the default config file tries to bind to localhost for both v4 and v6 and would like to silently ignore the error on v6 if disabled. This means that we sometimes want to ignore EADDRNOTAVAIL and other times we wanna fail. So this commit changes these main things: 1. Ignore all the errors we ignore for both explicitly requested bind address and a default implicit one. 2. Add a '-' prefix to allow EADDRNOTAVAIL be ignored (by default that's different than the previous behavior). 3. Restructure that function in a more readable and maintainable way see below. 4. Make the default behavior of listening to all achievable by setting a bind config directive to * (previously only possible by omitting it) 5. document everything. The old structure of this function was that even if there are no bind addresses requested, the loop that runs though the bind addresses runs at least once anyway! In that one iteration of the loop it binds to both v4 and v6 addresses, handles errors for each of them separately, and then eventually at the if-else chain, handles the error of the last bind attempt again! This was very hard to read and very error prone to maintain, instead now when the bind info is missing we create one with two entries, and run the simple loop twice.
Diffstat (limited to 'src/anet.c')
-rw-r--r--src/anet.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/src/anet.c b/src/anet.c
index 46ea7e145..e9615a128 100644
--- a/src/anet.c
+++ b/src/anet.c
@@ -487,6 +487,10 @@ static int _anetTcpServer(char *err, int port, char *bindaddr, int af, int backl
hints.ai_family = af;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE; /* No effect if bindaddr != NULL */
+ if (bindaddr && !strcmp("*", bindaddr))
+ bindaddr = NULL;
+ if (af == AF_INET6 && bindaddr && !strcmp("::*", bindaddr))
+ bindaddr = NULL;
if ((rv = getaddrinfo(bindaddr,_port,&hints,&servinfo)) != 0) {
anetSetError(err, "%s", gai_strerror(rv));