MINOR: fd: add a new function to only raise RLIMIT_NOFILE
In issue #1866 an issue was reported under docker, by which a user cannot lower the number of FD needed. It looks like a restriction imposed in this environment, but it results in an error while it ought not have to in the case of shrinking. This patch adds a new function raise_rlim_nofile() that takes the desired new setting, compares it to the current one, and only calls setrlimit() if one of the values in the new setting is larger than the older one. As such it will continue to emit warnings and errors in case of failure to raise the limit but will never shrink it. This patch is only preliminary to another one, but will have to be backported where relevant (likely only 2.6).
This commit is contained in:
parent
55d2e8577e
commit
922a907926
|
@ -78,6 +78,9 @@ ssize_t fd_write_frag_line(int fd, size_t maxlen, const struct ist pfx[], size_t
|
|||
/* close all FDs starting from <start> */
|
||||
void my_closefrom(int start);
|
||||
|
||||
struct rlimit;
|
||||
int raise_rlim_nofile(struct rlimit *old_limit, struct rlimit *new_limit);
|
||||
|
||||
int compute_poll_timeout(int next);
|
||||
void fd_leaving_poll(int wait_time, int status);
|
||||
|
||||
|
|
27
src/fd.c
27
src/fd.c
|
@ -885,6 +885,33 @@ void my_closefrom(int start)
|
|||
}
|
||||
#endif // defined(USE_POLL)
|
||||
|
||||
/* Sets the RLIMIT_NOFILE setting to <new_limit> and returns the previous one
|
||||
* in <old_limit> if the pointer is not NULL, even if set_rlimit() fails. The
|
||||
* two pointers may point to the same variable as the copy happens after
|
||||
* setting the new value. The value is only changed if at least one of the new
|
||||
* limits is strictly higher than the current one, otherwise returns 0 without
|
||||
* changing anything. The getrlimit() or setrlimit() syscall return value is
|
||||
* returned and errno is preserved.
|
||||
*/
|
||||
int raise_rlim_nofile(struct rlimit *old_limit, struct rlimit *new_limit)
|
||||
{
|
||||
struct rlimit limit = { };
|
||||
int ret = 0;
|
||||
|
||||
ret = getrlimit(RLIMIT_NOFILE, &limit);
|
||||
|
||||
if (ret == 0 &&
|
||||
(limit.rlim_max < new_limit->rlim_max ||
|
||||
limit.rlim_cur < new_limit->rlim_cur)) {
|
||||
ret = setrlimit(RLIMIT_NOFILE, new_limit);
|
||||
}
|
||||
|
||||
if (old_limit)
|
||||
*old_limit = limit;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Computes the bounded poll() timeout based on the next expiration timer <next>
|
||||
* by bounding it to MAX_DELAY_MS. <next> may equal TICK_ETERNITY. The pollers
|
||||
* just needs to call this function right before polling to get their timeout
|
||||
|
|
Loading…
Reference in New Issue