mirror of
https://codeberg.org/redict/redict.git
synced 2025-01-22 16:18:28 -05:00
Fix infinite loop on startup if ulimit too low
Fun fact: rlim_t is an unsigned long long on all platforms. Continually subtracting from a rlim_t makes it get smaller and smaller until it wraps, then you're up to 2^64-1. This was causing an infinite loop on Redis startup if your ulimit was extremely (almost comically) low. The case of (f > oldlimit) would never be met in a case like: f = 150 while (f > 20) f -= 128 Since f is unsigned, it can't go negative and would take on values of: Iteration 1: 150 - 128 => 22 Iteration 2: 22 - 128 => 18446744073709551510 Iterations 3-∞: ... To catch the wraparound, we use the previous value of f stored in limit.rlimit_cur. If we subtract from f and get a larger number than the value it had previously, we print an error and exit since we don't have enough file descriptors to help the user at this point. Thanks to @bs3g for the inspiration to fix this problem. Patches existed from @bs3g at antirez#1227, but I needed to repair a few other parts of Redis simultaneously, so I didn't get a chance to use them.
This commit is contained in:
parent
4a25983f8f
commit
90b844212d
11
src/redis.c
11
src/redis.c
@ -1519,6 +1519,17 @@ void adjustOpenFilesLimit(void) {
|
||||
limit.rlim_max = f;
|
||||
if (setrlimit(RLIMIT_NOFILE,&limit) != -1) break;
|
||||
f -= REDIS_EVENTLOOP_FDSET_INCR;
|
||||
if (f > limit.rlim_cur) {
|
||||
/* Instead of getting smaller, f just got bigger.
|
||||
* That means it wrapped around its unsigned floor
|
||||
* and is now closer to 2^64. We can't help anymore. */
|
||||
redisLog(REDIS_WARNING,"Failed to set max file limit. "
|
||||
"You requested maxclients of %d "
|
||||
"but your 'ulimit -n' is set to %llu. "
|
||||
"Please increase your 'ulimit -n' to at least %llu.",
|
||||
server.maxclients, oldlimit, maxfiles);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if (f < oldlimit) f = oldlimit;
|
||||
if (f != maxfiles) {
|
||||
|
Loading…
Reference in New Issue
Block a user