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>
37 #if !defined(HAVE_POLL_FINE) && \
38 !defined(USE_WINSOCK) && \
41 #error "this test requires FD_SETSIZE"
44 #define SAFETY_MARGIN (11)
46 #if defined(WIN32) || defined(_WIN32) || defined(MSDOS)
47 #define DEV_NULL "NUL"
49 #define DEV_NULL "/dev/null"
52 #if defined(HAVE_GETRLIMIT) && defined(HAVE_SETRLIMIT)
54 static int *fd = NULL;
55 static struct rlimit num_open;
56 static char msgbuff[256];
58 static void store_errmsg(const char *msg, int err)
61 snprintf(msgbuff, sizeof(msgbuff), "%s", msg);
63 snprintf(msgbuff, sizeof(msgbuff), "%s, errno %d, %s", msg, err,
67 static void close_file_descriptors(void)
69 for(num_open.rlim_cur = 0;
70 num_open.rlim_cur < num_open.rlim_max;
72 if(fd[num_open.rlim_cur] > 0)
73 close(fd[num_open.rlim_cur]);
78 static int fopen_works(void)
84 for(i = 0; i < 3; i++) {
87 for(i = 0; i < 3; i++) {
88 fpa[i] = fopen(DEV_NULL, FOPEN_READTEXT);
90 store_errmsg("fopen failed", ERRNO);
91 fprintf(stderr, "%s\n", msgbuff);
96 for(i = 0; i < 3; i++) {
103 static int rlimit(int keep_open)
107 int *memchunk = NULL;
113 char fmt_lu[] = "%lu";
115 char fmt_llu[] = "%llu";
117 if(sizeof(rl.rlim_max) > sizeof(long))
121 fmt = (sizeof(rl.rlim_max) < sizeof(long))?fmt_u:fmt_lu;
123 /* get initial open file limits */
125 if(getrlimit(RLIMIT_NOFILE, &rl) != 0) {
126 store_errmsg("getrlimit() failed", ERRNO);
127 fprintf(stderr, "%s\n", msgbuff);
131 /* show initial open file limits */
134 if(rl.rlim_cur == RLIM_INFINITY)
135 strcpy(strbuff, "INFINITY");
138 snprintf(strbuff, sizeof(strbuff), fmt, rl.rlim_cur);
139 fprintf(stderr, "initial soft limit: %s\n", strbuff);
142 if(rl.rlim_max == RLIM_INFINITY)
143 strcpy(strbuff, "INFINITY");
146 snprintf(strbuff, sizeof(strbuff), fmt, rl.rlim_max);
147 fprintf(stderr, "initial hard limit: %s\n", strbuff);
150 * if soft limit and hard limit are different we ask the
151 * system to raise soft limit all the way up to the hard
152 * limit. Due to some other system limit the soft limit
153 * might not be raised up to the hard limit. So from this
154 * point the resulting soft limit is our limit. Trying to
155 * open more than soft limit file descriptors will fail.
158 if(rl.rlim_cur != rl.rlim_max) {
161 if((rl.rlim_cur > 0) &&
162 (rl.rlim_cur < OPEN_MAX)) {
163 fprintf(stderr, "raising soft limit up to OPEN_MAX\n");
164 rl.rlim_cur = OPEN_MAX;
165 if(setrlimit(RLIMIT_NOFILE, &rl) != 0) {
166 /* on failure don't abort just issue a warning */
167 store_errmsg("setrlimit() failed", ERRNO);
168 fprintf(stderr, "%s\n", msgbuff);
174 fprintf(stderr, "raising soft limit up to hard limit\n");
175 rl.rlim_cur = rl.rlim_max;
176 if(setrlimit(RLIMIT_NOFILE, &rl) != 0) {
177 /* on failure don't abort just issue a warning */
178 store_errmsg("setrlimit() failed", ERRNO);
179 fprintf(stderr, "%s\n", msgbuff);
183 /* get current open file limits */
185 if(getrlimit(RLIMIT_NOFILE, &rl) != 0) {
186 store_errmsg("getrlimit() failed", ERRNO);
187 fprintf(stderr, "%s\n", msgbuff);
191 /* show current open file limits */
194 if(rl.rlim_cur == RLIM_INFINITY)
195 strcpy(strbuff, "INFINITY");
198 snprintf(strbuff, sizeof(strbuff), fmt, rl.rlim_cur);
199 fprintf(stderr, "current soft limit: %s\n", strbuff);
202 if(rl.rlim_max == RLIM_INFINITY)
203 strcpy(strbuff, "INFINITY");
206 snprintf(strbuff, sizeof(strbuff), fmt, rl.rlim_max);
207 fprintf(stderr, "current hard limit: %s\n", strbuff);
209 } /* (rl.rlim_cur != rl.rlim_max) */
212 * test 537 is all about testing libcurl functionality
213 * when the system has nearly exhausted the number of
214 * available file descriptors. Test 537 will try to run
215 * with a very small number of file descriptors available.
216 * This implies that any file descriptor which is open
217 * when the test runs will have a number in the high range
218 * of whatever the system supports.
222 * reserve a chunk of memory before opening file descriptors to
223 * avoid a low memory condition once the file descriptors are
224 * open. System conditions that could make the test fail should
225 * be addressed in the precheck phase. This chunk of memory shall
226 * be always free()ed before exiting the rlimit() function so
227 * that it becomes available to the test.
230 for(nitems = i = 1; nitems <= i; i *= 2)
235 num_open.rlim_max = sizeof(*memchunk) * (size_t)nitems;
236 snprintf(strbuff, sizeof(strbuff), fmt, num_open.rlim_max);
237 fprintf(stderr, "allocating memchunk %s byte array\n", strbuff);
238 memchunk = malloc(sizeof(*memchunk) * (size_t)nitems);
240 fprintf(stderr, "memchunk, malloc() failed\n");
243 } while(nitems && !memchunk);
245 store_errmsg("memchunk, malloc() failed", ERRNO);
246 fprintf(stderr, "%s\n", msgbuff);
250 /* initialize it to fight lazy allocation */
252 fprintf(stderr, "initializing memchunk array\n");
254 for(i = 0; i < nitems; i++)
257 /* set the number of file descriptors we will try to open */
260 if((rl.rlim_cur > 0) && (rl.rlim_cur != RLIM_INFINITY)) {
262 if(rl.rlim_cur > 0) {
264 /* soft limit minus SAFETY_MARGIN */
265 num_open.rlim_max = rl.rlim_cur - SAFETY_MARGIN;
268 /* a huge number of file descriptors */
269 for(nitems = i = 1; nitems <= i; i *= 2)
273 num_open.rlim_max = nitems;
276 /* verify that we won't overflow size_t in malloc() */
278 if((size_t)(num_open.rlim_max) > ((size_t)-1) / sizeof(*fd)) {
279 snprintf(strbuff1, sizeof(strbuff1), fmt, num_open.rlim_max);
280 snprintf(strbuff, sizeof(strbuff), "unable to allocate an array for %s "
281 "file descriptors, would overflow size_t", strbuff1);
282 store_errmsg(strbuff, 0);
283 fprintf(stderr, "%s\n", msgbuff);
288 /* allocate array for file descriptors */
291 snprintf(strbuff, sizeof(strbuff), fmt, num_open.rlim_max);
292 fprintf(stderr, "allocating array for %s file descriptors\n", strbuff);
293 fd = malloc(sizeof(*fd) * (size_t)(num_open.rlim_max));
295 fprintf(stderr, "fd, malloc() failed\n");
296 num_open.rlim_max /= 2;
298 } while(num_open.rlim_max && !fd);
300 store_errmsg("fd, malloc() failed", ERRNO);
301 fprintf(stderr, "%s\n", msgbuff);
306 /* initialize it to fight lazy allocation */
308 fprintf(stderr, "initializing fd array\n");
310 for(num_open.rlim_cur = 0;
311 num_open.rlim_cur < num_open.rlim_max;
313 fd[num_open.rlim_cur] = -1;
315 snprintf(strbuff, sizeof(strbuff), fmt, num_open.rlim_max);
316 fprintf(stderr, "trying to open %s file descriptors\n", strbuff);
318 /* open a dummy descriptor */
320 fd[0] = open(DEV_NULL, O_RDONLY);
322 snprintf(strbuff, sizeof(strbuff), "opening of %s failed", DEV_NULL);
323 store_errmsg(strbuff, ERRNO);
324 fprintf(stderr, "%s\n", msgbuff);
331 /* create a bunch of file descriptors */
333 for(num_open.rlim_cur = 1;
334 num_open.rlim_cur < num_open.rlim_max;
335 num_open.rlim_cur++) {
337 fd[num_open.rlim_cur] = dup(fd[0]);
339 if(fd[num_open.rlim_cur] < 0) {
341 fd[num_open.rlim_cur] = -1;
343 snprintf(strbuff1, sizeof(strbuff1), fmt, num_open.rlim_cur);
344 snprintf(strbuff, sizeof(strbuff), "dup() attempt %s failed", strbuff1);
345 fprintf(stderr, "%s\n", strbuff);
347 snprintf(strbuff1, sizeof(strbuff1), fmt, num_open.rlim_cur);
348 snprintf(strbuff, sizeof(strbuff), "fds system limit seems close to %s",
350 fprintf(stderr, "%s\n", strbuff);
352 num_open.rlim_max = num_open.rlim_cur - SAFETY_MARGIN;
354 num_open.rlim_cur -= num_open.rlim_max;
355 snprintf(strbuff1, sizeof(strbuff1), fmt, num_open.rlim_cur);
356 snprintf(strbuff, sizeof(strbuff), "closing %s file descriptors",
358 fprintf(stderr, "%s\n", strbuff);
360 for(num_open.rlim_cur = num_open.rlim_max;
361 fd[num_open.rlim_cur] >= 0;
362 num_open.rlim_cur++) {
363 close(fd[num_open.rlim_cur]);
364 fd[num_open.rlim_cur] = -1;
367 snprintf(strbuff, sizeof(strbuff), fmt, num_open.rlim_max);
368 fprintf(stderr, "shrinking array for %s file descriptors\n", strbuff);
370 /* we don't care if we can't shrink it */
372 tmpfd = realloc(fd, sizeof(*fd) * (size_t)(num_open.rlim_max));
384 snprintf(strbuff, sizeof(strbuff), fmt, num_open.rlim_max);
385 fprintf(stderr, "%s file descriptors open\n", strbuff);
387 #if !defined(HAVE_POLL_FINE) && \
388 !defined(USE_WINSOCK) && \
392 * when using select() instead of poll() we cannot test
393 * libcurl functionality with a socket number equal or
394 * greater than FD_SETSIZE. In any case, macro VERIFY_SOCK
395 * in lib/select.c enforces this check and protects libcurl
396 * from a possible crash. The effect of this protection
397 * is that test 537 will always fail, since the actual
398 * call to select() never takes place. We skip test 537
399 * with an indication that select limit would be exceeded.
402 num_open.rlim_cur = FD_SETSIZE - SAFETY_MARGIN;
403 if(num_open.rlim_max > num_open.rlim_cur) {
404 snprintf(strbuff, sizeof(strbuff), "select limit is FD_SETSIZE %d",
406 store_errmsg(strbuff, 0);
407 fprintf(stderr, "%s\n", msgbuff);
408 close_file_descriptors();
413 num_open.rlim_cur = FD_SETSIZE - SAFETY_MARGIN;
415 rl.rlim_cur < num_open.rlim_max;
417 if((fd[rl.rlim_cur] > 0) &&
418 ((unsigned int)fd[rl.rlim_cur] > num_open.rlim_cur)) {
419 snprintf(strbuff, sizeof(strbuff), "select limit is FD_SETSIZE %d",
421 store_errmsg(strbuff, 0);
422 fprintf(stderr, "%s\n", msgbuff);
423 close_file_descriptors();
429 #endif /* using a FD_SETSIZE bound select() */
432 * Old or 'backwards compatible' implementations of stdio do not allow
433 * handling of streams with an underlying file descriptor number greater
434 * than 255, even when allowing high numbered file descriptors for sockets.
435 * At this point we have a big number of file descriptors which have been
436 * opened using dup(), so lets test the stdio implementation and discover
437 * if it is capable of fopen()ing some additional files.
441 snprintf(strbuff1, sizeof(strbuff1), fmt, num_open.rlim_max);
442 snprintf(strbuff, sizeof(strbuff), "fopen fails with %s fds open",
444 fprintf(stderr, "%s\n", msgbuff);
445 snprintf(strbuff, sizeof(strbuff), "fopen fails with lots of fds open");
446 store_errmsg(strbuff, 0);
447 close_file_descriptors();
452 /* free the chunk of memory we were reserving so that it
453 becomes becomes available to the test */
457 /* close file descriptors unless instructed to keep them */
460 close_file_descriptors();
471 if(!strcmp(URL, "check")) {
472 /* used by the test script to ask if we can run this test or not */
474 fprintf(stdout, "rlimit problem: %s\n", msgbuff);
477 return 0; /* sure, run this! */
482 return TEST_ERR_MAJOR_BAD;
485 /* run the test with the bunch of open file descriptors
486 and close them all once the test is over */
488 if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
489 fprintf(stderr, "curl_global_init() failed\n");
490 close_file_descriptors();
491 return TEST_ERR_MAJOR_BAD;
494 if((curl = curl_easy_init()) == NULL) {
495 fprintf(stderr, "curl_easy_init() failed\n");
496 close_file_descriptors();
497 curl_global_cleanup();
498 return TEST_ERR_MAJOR_BAD;
501 test_setopt(curl, CURLOPT_URL, URL);
502 test_setopt(curl, CURLOPT_HEADER, 1L);
504 res = curl_easy_perform(curl);
508 close_file_descriptors();
509 curl_easy_cleanup(curl);
510 curl_global_cleanup();
515 #else /* defined(HAVE_GETRLIMIT) && defined(HAVE_SETRLIMIT) */
520 printf("system lacks necessary system function(s)");
521 return 1; /* skip test */
524 #endif /* defined(HAVE_GETRLIMIT) && defined(HAVE_SETRLIMIT) */