|
10 | 10 | #include <sync.h> |
11 | 11 | #include <tinyformat.h> |
12 | 12 | #include <util/byte_units.h> // IWYU pragma: keep |
| 13 | +#include <util/check.h> |
13 | 14 | #include <util/fs.h> |
14 | 15 | #include <util/log.h> |
15 | 16 | #include <util/syserror.h> |
16 | 17 |
|
17 | 18 | #include <cerrno> |
18 | 19 | #include <fstream> |
| 20 | +#include <limits> |
19 | 21 | #include <map> |
20 | 22 | #include <memory> |
21 | 23 | #include <optional> |
@@ -154,27 +156,40 @@ bool TruncateFile(FILE* file, unsigned int length) |
154 | 156 | #endif |
155 | 157 | } |
156 | 158 |
|
157 | | -/** |
158 | | - * this function tries to raise the file descriptor limit to the requested number. |
159 | | - * It returns the actual file descriptor limit (which may be more or less than nMinFD) |
160 | | - */ |
161 | | -int RaiseFileDescriptorLimit(int nMinFD) |
| 159 | +int RaiseFileDescriptorLimit(int min_fd) |
162 | 160 | { |
| 161 | + Assert(min_fd >= 0); |
163 | 162 | #if defined(WIN32) |
164 | 163 | return 2048; |
165 | 164 | #else |
166 | 165 | struct rlimit limitFD; |
167 | 166 | if (getrlimit(RLIMIT_NOFILE, &limitFD) != -1) { |
168 | | - if (limitFD.rlim_cur < (rlim_t)nMinFD) { |
169 | | - limitFD.rlim_cur = nMinFD; |
170 | | - if (limitFD.rlim_cur > limitFD.rlim_max) |
| 167 | + // If the current soft limit is already higher, don't raise it |
| 168 | + if (limitFD.rlim_cur != RLIM_INFINITY && std::cmp_less(limitFD.rlim_cur, min_fd)) { |
| 169 | + const auto current_limit{limitFD.rlim_cur}; |
| 170 | + static_assert(std::in_range<rlim_t>(std::numeric_limits<int>::max())); |
| 171 | + limitFD.rlim_cur = static_cast<rlim_t>(min_fd); |
| 172 | + // Don't raise soft limit beyond hard limit |
| 173 | + if ((limitFD.rlim_max != RLIM_INFINITY) && (limitFD.rlim_cur > limitFD.rlim_max)) { |
171 | 174 | limitFD.rlim_cur = limitFD.rlim_max; |
172 | | - setrlimit(RLIMIT_NOFILE, &limitFD); |
173 | | - getrlimit(RLIMIT_NOFILE, &limitFD); |
| 175 | + } |
| 176 | + if (current_limit != limitFD.rlim_cur) { |
| 177 | + setrlimit(RLIMIT_NOFILE, &limitFD); |
| 178 | + getrlimit(RLIMIT_NOFILE, &limitFD); |
| 179 | + } |
| 180 | + } |
| 181 | + // Check the (possibly raised) current soft limit against the special |
| 182 | + // value of RLIM_INFINITY. Some platforms implement this as the maximum |
| 183 | + // uint64, others as int64 (-1). Avoid casting even if the return type |
| 184 | + // is changed to uint64_t. We also cap unlikely but possible values |
| 185 | + // that would overflow int. |
| 186 | + if (limitFD.rlim_cur == RLIM_INFINITY || |
| 187 | + std::cmp_greater_equal(limitFD.rlim_cur, std::numeric_limits<int>::max())) { |
| 188 | + return std::numeric_limits<int>::max(); |
174 | 189 | } |
175 | | - return limitFD.rlim_cur; |
| 190 | + return static_cast<int>(limitFD.rlim_cur); |
176 | 191 | } |
177 | | - return nMinFD; // getrlimit failed, assume it's fine |
| 192 | + return min_fd; // getrlimit failed, assume it's fine |
178 | 193 | #endif |
179 | 194 | } |
180 | 195 |
|
|
0 commit comments