1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at https://curl.haxx.se/docs/copyright.html.
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ***************************************************************************/
24 #ifdef HAVE_SYS_RESOURCE_H
25 #include <sys/resource.h>
36 #error "this test requires FD_SETSIZE"
39 #define SAFETY_MARGIN (16)
40 #define NUM_OPEN (FD_SETSIZE + 10)
41 #define NUM_NEEDED (NUM_OPEN + SAFETY_MARGIN)
43 #if defined(WIN32) || defined(_WIN32) || defined(MSDOS)
44 #define DEV_NULL "NUL"
46 #define DEV_NULL "/dev/null"
49 #if defined(HAVE_GETRLIMIT) && defined(HAVE_SETRLIMIT)
51 static int *fd = NULL;
52 static struct rlimit num_open;
53 static char msgbuff[256];
55 static void store_errmsg(const char *msg, int err)
58 snprintf(msgbuff, sizeof(msgbuff), "%s", msg);
60 snprintf(msgbuff, sizeof(msgbuff), "%s, errno %d, %s", msg,
64 static void close_file_descriptors(void)
66 for(num_open.rlim_cur = 0;
67 num_open.rlim_cur < num_open.rlim_max;
69 if(fd[num_open.rlim_cur] > 0)
70 close(fd[num_open.rlim_cur]);
75 static int fopen_works(void)
81 for(i = 0; i < 3; i++) {
84 for(i = 0; i < 3; i++) {
85 fpa[i] = fopen(DEV_NULL, FOPEN_READTEXT);
87 store_errmsg("fopen failed", errno);
88 fprintf(stderr, "%s\n", msgbuff);
93 for(i = 0; i < 3; i++) {
100 static int rlimit(int keep_open)
103 int *memchunk = NULL;
110 char fmt_lu[] = "%lu";
112 char fmt_llu[] = "%llu";
114 if(sizeof(rl.rlim_max) > sizeof(long))
118 fmt = (sizeof(rl.rlim_max) < sizeof(long))?fmt_u:fmt_lu;
120 /* get initial open file limits */
122 if(getrlimit(RLIMIT_NOFILE, &rl) != 0) {
123 store_errmsg("getrlimit() failed", errno);
124 fprintf(stderr, "%s\n", msgbuff);
128 /* show initial open file limits */
131 if(rl.rlim_cur == RLIM_INFINITY)
132 strcpy(strbuff, "INFINITY");
135 snprintf(strbuff, sizeof(strbuff), fmt, rl.rlim_cur);
136 fprintf(stderr, "initial soft limit: %s\n", strbuff);
139 if(rl.rlim_max == RLIM_INFINITY)
140 strcpy(strbuff, "INFINITY");
143 snprintf(strbuff, sizeof(strbuff), fmt, rl.rlim_max);
144 fprintf(stderr, "initial hard limit: %s\n", strbuff);
146 /* show our constants */
148 fprintf(stderr, "test518 FD_SETSIZE: %d\n", FD_SETSIZE);
149 fprintf(stderr, "test518 NUM_OPEN : %d\n", NUM_OPEN);
150 fprintf(stderr, "test518 NUM_NEEDED: %d\n", NUM_NEEDED);
153 * if soft limit and hard limit are different we ask the
154 * system to raise soft limit all the way up to the hard
155 * limit. Due to some other system limit the soft limit
156 * might not be raised up to the hard limit. So from this
157 * point the resulting soft limit is our limit. Trying to
158 * open more than soft limit file descriptors will fail.
161 if(rl.rlim_cur != rl.rlim_max) {
164 if((rl.rlim_cur > 0) &&
165 (rl.rlim_cur < OPEN_MAX)) {
166 fprintf(stderr, "raising soft limit up to OPEN_MAX\n");
167 rl.rlim_cur = OPEN_MAX;
168 if(setrlimit(RLIMIT_NOFILE, &rl) != 0) {
169 /* on failure don't abort just issue a warning */
170 store_errmsg("setrlimit() failed", errno);
171 fprintf(stderr, "%s\n", msgbuff);
177 fprintf(stderr, "raising soft limit up to hard limit\n");
178 rl.rlim_cur = rl.rlim_max;
179 if(setrlimit(RLIMIT_NOFILE, &rl) != 0) {
180 /* on failure don't abort just issue a warning */
181 store_errmsg("setrlimit() failed", errno);
182 fprintf(stderr, "%s\n", msgbuff);
186 /* get current open file limits */
188 if(getrlimit(RLIMIT_NOFILE, &rl) != 0) {
189 store_errmsg("getrlimit() failed", errno);
190 fprintf(stderr, "%s\n", msgbuff);
194 /* show current open file limits */
197 if(rl.rlim_cur == RLIM_INFINITY)
198 strcpy(strbuff, "INFINITY");
201 snprintf(strbuff, sizeof(strbuff), fmt, rl.rlim_cur);
202 fprintf(stderr, "current soft limit: %s\n", strbuff);
205 if(rl.rlim_max == RLIM_INFINITY)
206 strcpy(strbuff, "INFINITY");
209 snprintf(strbuff, sizeof(strbuff), fmt, rl.rlim_max);
210 fprintf(stderr, "current hard limit: %s\n", strbuff);
212 } /* (rl.rlim_cur != rl.rlim_max) */
215 * test 518 is all about testing libcurl functionality
216 * when more than FD_SETSIZE file descriptors are open.
217 * This means that if for any reason we are not able to
218 * open more than FD_SETSIZE file descriptors then test
219 * 518 should not be run.
223 * verify that soft limit is higher than NUM_NEEDED,
224 * which is the number of file descriptors we would
225 * try to open plus SAFETY_MARGIN to not exhaust the
226 * file descriptor pool
229 num_open.rlim_cur = NUM_NEEDED;
231 if((rl.rlim_cur > 0) &&
233 (rl.rlim_cur != RLIM_INFINITY) &&
235 (rl.rlim_cur <= num_open.rlim_cur)) {
236 snprintf(strbuff2, sizeof(strbuff2), fmt, rl.rlim_cur);
237 snprintf(strbuff1, sizeof(strbuff1), fmt, num_open.rlim_cur);
238 snprintf(strbuff, sizeof(strbuff), "fds needed %s > system limit %s",
240 store_errmsg(strbuff, 0);
241 fprintf(stderr, "%s\n", msgbuff);
246 * reserve a chunk of memory before opening file descriptors to
247 * avoid a low memory condition once the file descriptors are
248 * open. System conditions that could make the test fail should
249 * be addressed in the precheck phase. This chunk of memory shall
250 * be always free()ed before exiting the rlimit() function so
251 * that it becomes available to the test.
254 for(nitems = i = 1; nitems <= i; i *= 2)
259 num_open.rlim_max = sizeof(*memchunk) * (size_t)nitems;
260 snprintf(strbuff, sizeof(strbuff), fmt, num_open.rlim_max);
261 fprintf(stderr, "allocating memchunk %s byte array\n", strbuff);
262 memchunk = malloc(sizeof(*memchunk) * (size_t)nitems);
264 fprintf(stderr, "memchunk, malloc() failed\n");
267 } while(nitems && !memchunk);
269 store_errmsg("memchunk, malloc() failed", errno);
270 fprintf(stderr, "%s\n", msgbuff);
274 /* initialize it to fight lazy allocation */
276 fprintf(stderr, "initializing memchunk array\n");
278 for(i = 0; i < nitems; i++)
281 /* set the number of file descriptors we will try to open */
283 num_open.rlim_max = NUM_OPEN;
285 /* verify that we won't overflow size_t in malloc() */
287 if((size_t)(num_open.rlim_max) > ((size_t)-1) / sizeof(*fd)) {
288 snprintf(strbuff1, sizeof(strbuff1), fmt, num_open.rlim_max);
289 snprintf(strbuff, sizeof(strbuff), "unable to allocate an array for %s "
290 "file descriptors, would overflow size_t", strbuff1);
291 store_errmsg(strbuff, 0);
292 fprintf(stderr, "%s\n", msgbuff);
297 /* allocate array for file descriptors */
299 snprintf(strbuff, sizeof(strbuff), fmt, num_open.rlim_max);
300 fprintf(stderr, "allocating array for %s file descriptors\n", strbuff);
302 fd = malloc(sizeof(*fd) * (size_t)(num_open.rlim_max));
304 store_errmsg("fd, malloc() failed", errno);
305 fprintf(stderr, "%s\n", msgbuff);
310 /* initialize it to fight lazy allocation */
312 fprintf(stderr, "initializing fd array\n");
314 for(num_open.rlim_cur = 0;
315 num_open.rlim_cur < num_open.rlim_max;
317 fd[num_open.rlim_cur] = -1;
319 snprintf(strbuff, sizeof(strbuff), fmt, num_open.rlim_max);
320 fprintf(stderr, "trying to open %s file descriptors\n", strbuff);
322 /* open a dummy descriptor */
324 fd[0] = open(DEV_NULL, O_RDONLY);
326 snprintf(strbuff, sizeof(strbuff), "opening of %s failed", DEV_NULL);
327 store_errmsg(strbuff, errno);
328 fprintf(stderr, "%s\n", msgbuff);
335 /* create a bunch of file descriptors */
337 for(num_open.rlim_cur = 1;
338 num_open.rlim_cur < num_open.rlim_max;
339 num_open.rlim_cur++) {
341 fd[num_open.rlim_cur] = dup(fd[0]);
343 if(fd[num_open.rlim_cur] < 0) {
345 fd[num_open.rlim_cur] = -1;
347 snprintf(strbuff1, sizeof(strbuff1), fmt, num_open.rlim_cur);
348 snprintf(strbuff, sizeof(strbuff), "dup() attempt %s failed", strbuff1);
349 fprintf(stderr, "%s\n", strbuff);
351 snprintf(strbuff1, sizeof(strbuff), fmt, num_open.rlim_cur);
352 snprintf(strbuff, sizeof(strbuff), "fds system limit seems close to %s",
354 fprintf(stderr, "%s\n", strbuff);
356 num_open.rlim_max = NUM_NEEDED;
358 snprintf(strbuff2, sizeof(strbuff2), fmt, num_open.rlim_max);
359 snprintf(strbuff1, sizeof(strbuff1), fmt, num_open.rlim_cur);
360 snprintf(strbuff, sizeof(strbuff), "fds needed %s > system limit %s",
362 store_errmsg(strbuff, 0);
363 fprintf(stderr, "%s\n", msgbuff);
365 for(num_open.rlim_cur = 0;
366 fd[num_open.rlim_cur] >= 0;
368 close(fd[num_open.rlim_cur]);
378 snprintf(strbuff, sizeof(strbuff), fmt, num_open.rlim_max);
379 fprintf(stderr, "%s file descriptors open\n", strbuff);
381 #if !defined(HAVE_POLL_FINE) && \
382 !defined(USE_WINSOCK) && \
386 * when using select() instead of poll() we cannot test
387 * libcurl functionality with a socket number equal or
388 * greater than FD_SETSIZE. In any case, macro VERIFY_SOCK
389 * in lib/select.c enforces this check and protects libcurl
390 * from a possible crash. The effect of this protection
391 * is that test 518 will always fail, since the actual
392 * call to select() never takes place. We skip test 518
393 * with an indication that select limit would be exceeded.
396 num_open.rlim_cur = FD_SETSIZE - SAFETY_MARGIN;
397 if(num_open.rlim_max > num_open.rlim_cur) {
398 snprintf(strbuff, sizeof(strbuff), "select limit is FD_SETSIZE %d",
400 store_errmsg(strbuff, 0);
401 fprintf(stderr, "%s\n", msgbuff);
402 close_file_descriptors();
407 num_open.rlim_cur = FD_SETSIZE - SAFETY_MARGIN;
409 rl.rlim_cur < num_open.rlim_max;
411 if((fd[rl.rlim_cur] > 0) &&
412 ((unsigned int)fd[rl.rlim_cur] > num_open.rlim_cur)) {
413 snprintf(strbuff, sizeof(strbuff), "select limit is FD_SETSIZE %d",
415 store_errmsg(strbuff, 0);
416 fprintf(stderr, "%s\n", msgbuff);
417 close_file_descriptors();
423 #endif /* using a FD_SETSIZE bound select() */
426 * Old or 'backwards compatible' implementations of stdio do not allow
427 * handling of streams with an underlying file descriptor number greater
428 * than 255, even when allowing high numbered file descriptors for sockets.
429 * At this point we have a big number of file descriptors which have been
430 * opened using dup(), so lets test the stdio implementation and discover
431 * if it is capable of fopen()ing some additional files.
435 snprintf(strbuff1, sizeof(strbuff1), fmt, num_open.rlim_max);
436 snprintf(strbuff, sizeof(strbuff),
437 "fopen fails with %s fds open()",
439 fprintf(stderr, "%s\n", msgbuff);
440 snprintf(strbuff, sizeof(strbuff),
441 "fopen fails with lots of fds open()");
442 store_errmsg(strbuff, 0);
443 close_file_descriptors();
448 /* free the chunk of memory we were reserving so that it
449 becomes becomes available to the test */
453 /* close file descriptors unless instructed to keep them */
456 close_file_descriptors();
467 if(!strcmp(URL, "check")) {
468 /* used by the test script to ask if we can run this test or not */
470 fprintf(stdout, "rlimit problem: %s\n", msgbuff);
473 return 0; /* sure, run this! */
478 return TEST_ERR_MAJOR_BAD;
481 /* run the test with the bunch of open file descriptors
482 and close them all once the test is over */
484 if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
485 fprintf(stderr, "curl_global_init() failed\n");
486 close_file_descriptors();
487 return TEST_ERR_MAJOR_BAD;
490 curl = curl_easy_init();
492 fprintf(stderr, "curl_easy_init() failed\n");
493 close_file_descriptors();
494 curl_global_cleanup();
495 return TEST_ERR_MAJOR_BAD;
498 test_setopt(curl, CURLOPT_URL, URL);
499 test_setopt(curl, CURLOPT_HEADER, 1L);
501 res = curl_easy_perform(curl);
505 close_file_descriptors();
506 curl_easy_cleanup(curl);
507 curl_global_cleanup();
512 #else /* defined(HAVE_GETRLIMIT) && defined(HAVE_SETRLIMIT) */
517 printf("system lacks necessary system function(s)");
518 return 1; /* skip test */
521 #endif /* defined(HAVE_GETRLIMIT) && defined(HAVE_SETRLIMIT) */