1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel (at) haxx.se>, et al. 9 * 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. 13 * 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. 17 * 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 * KIND, either express or implied. 20 * 21 ***************************************************************************/ 22 #include "test.h" 23 24 #ifdef HAVE_SYS_RESOURCE_H 25 #include <sys/resource.h> 26 #endif 27 #ifdef HAVE_FCNTL_H 28 #include <fcntl.h> 29 #endif 30 #ifdef HAVE_LIMITS_H 31 #include <limits.h> 32 #endif 33 34 #include "warnless.h" 35 #include "memdebug.h" 36 37 #if !defined(HAVE_POLL_FINE) && \ 38 !defined(USE_WINSOCK) && \ 39 !defined(TPF) && \ 40 !defined(FD_SETSIZE) 41 #error "this test requires FD_SETSIZE" 42 #endif 43 44 #define SAFETY_MARGIN (11) 45 46 #if defined(WIN32) || defined(_WIN32) || defined(MSDOS) 47 #define DEV_NULL "NUL" 48 #else 49 #define DEV_NULL "/dev/null" 50 #endif 51 52 #if defined(HAVE_GETRLIMIT) && defined(HAVE_SETRLIMIT) 53 54 static int *fd = NULL; 55 static struct rlimit num_open; 56 static char msgbuff[256]; 57 58 static void store_errmsg(const char *msg, int err) 59 { 60 if(!err) 61 snprintf(msgbuff, sizeof(msgbuff), "%s", msg); 62 else 63 snprintf(msgbuff, sizeof(msgbuff), "%s, errno %d, %s", msg, err, 64 strerror(err)); 65 } 66 67 static void close_file_descriptors(void) 68 { 69 for(num_open.rlim_cur = 0; 70 num_open.rlim_cur < num_open.rlim_max; 71 num_open.rlim_cur++) 72 if(fd[num_open.rlim_cur] > 0) 73 close(fd[num_open.rlim_cur]); 74 free(fd); 75 fd = NULL; 76 } 77 78 static int fopen_works(void) 79 { 80 FILE *fpa[3]; 81 int i; 82 int ret = 1; 83 84 for(i = 0; i < 3; i++) { 85 fpa[i] = NULL; 86 } 87 for(i = 0; i < 3; i++) { 88 fpa[i] = fopen(DEV_NULL, FOPEN_READTEXT); 89 if(fpa[i] == NULL) { 90 store_errmsg("fopen failed", ERRNO); 91 fprintf(stderr, "%s\n", msgbuff); 92 ret = 0; 93 break; 94 } 95 } 96 for(i = 0; i < 3; i++) { 97 if(fpa[i] != NULL) 98 fclose(fpa[i]); 99 } 100 return ret; 101 } 102 103 static int rlimit(int keep_open) 104 { 105 int *tmpfd; 106 int nitems, i; 107 int *memchunk = NULL; 108 char *fmt; 109 struct rlimit rl; 110 char strbuff[256]; 111 char strbuff1[81]; 112 char fmt_u[] = "%u"; 113 char fmt_lu[] = "%lu"; 114 #ifdef HAVE_LONGLONG 115 char fmt_llu[] = "%llu"; 116 117 if(sizeof(rl.rlim_max) > sizeof(long)) 118 fmt = fmt_llu; 119 else 120 #endif 121 fmt = (sizeof(rl.rlim_max) < sizeof(long))?fmt_u:fmt_lu; 122 123 /* get initial open file limits */ 124 125 if(getrlimit(RLIMIT_NOFILE, &rl) != 0) { 126 store_errmsg("getrlimit() failed", ERRNO); 127 fprintf(stderr, "%s\n", msgbuff); 128 return -1; 129 } 130 131 /* show initial open file limits */ 132 133 #ifdef RLIM_INFINITY 134 if(rl.rlim_cur == RLIM_INFINITY) 135 strcpy(strbuff, "INFINITY"); 136 else 137 #endif 138 snprintf(strbuff, sizeof(strbuff), fmt, rl.rlim_cur); 139 fprintf(stderr, "initial soft limit: %s\n", strbuff); 140 141 #ifdef RLIM_INFINITY 142 if(rl.rlim_max == RLIM_INFINITY) 143 strcpy(strbuff, "INFINITY"); 144 else 145 #endif 146 snprintf(strbuff, sizeof(strbuff), fmt, rl.rlim_max); 147 fprintf(stderr, "initial hard limit: %s\n", strbuff); 148 149 /* 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. 156 */ 157 158 if(rl.rlim_cur != rl.rlim_max) { 159 160 #ifdef OPEN_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); 169 msgbuff[0] = '\0'; 170 } 171 } 172 #endif 173 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); 180 msgbuff[0] = '\0'; 181 } 182 183 /* get current open file limits */ 184 185 if(getrlimit(RLIMIT_NOFILE, &rl) != 0) { 186 store_errmsg("getrlimit() failed", ERRNO); 187 fprintf(stderr, "%s\n", msgbuff); 188 return -3; 189 } 190 191 /* show current open file limits */ 192 193 #ifdef RLIM_INFINITY 194 if(rl.rlim_cur == RLIM_INFINITY) 195 strcpy(strbuff, "INFINITY"); 196 else 197 #endif 198 snprintf(strbuff, sizeof(strbuff), fmt, rl.rlim_cur); 199 fprintf(stderr, "current soft limit: %s\n", strbuff); 200 201 #ifdef RLIM_INFINITY 202 if(rl.rlim_max == RLIM_INFINITY) 203 strcpy(strbuff, "INFINITY"); 204 else 205 #endif 206 snprintf(strbuff, sizeof(strbuff), fmt, rl.rlim_max); 207 fprintf(stderr, "current hard limit: %s\n", strbuff); 208 209 } /* (rl.rlim_cur != rl.rlim_max) */ 210 211 /* 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. 219 */ 220 221 /* 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. 228 */ 229 230 for(nitems = i = 1; nitems <= i; i *= 2) 231 nitems = i; 232 if(nitems > 0x7fff) 233 nitems = 0x40000; 234 do { 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); 239 if(!memchunk) { 240 fprintf(stderr, "memchunk, malloc() failed\n"); 241 nitems /= 2; 242 } 243 } while(nitems && !memchunk); 244 if(!memchunk) { 245 store_errmsg("memchunk, malloc() failed", ERRNO); 246 fprintf(stderr, "%s\n", msgbuff); 247 return -4; 248 } 249 250 /* initialize it to fight lazy allocation */ 251 252 fprintf(stderr, "initializing memchunk array\n"); 253 254 for(i = 0; i < nitems; i++) 255 memchunk[i] = -1; 256 257 /* set the number of file descriptors we will try to open */ 258 259 #ifdef RLIM_INFINITY 260 if((rl.rlim_cur > 0) && (rl.rlim_cur != RLIM_INFINITY)) { 261 #else 262 if(rl.rlim_cur > 0) { 263 #endif 264 /* soft limit minus SAFETY_MARGIN */ 265 num_open.rlim_max = rl.rlim_cur - SAFETY_MARGIN; 266 } 267 else { 268 /* a huge number of file descriptors */ 269 for(nitems = i = 1; nitems <= i; i *= 2) 270 nitems = i; 271 if(nitems > 0x7fff) 272 nitems = 0x40000; 273 num_open.rlim_max = nitems; 274 } 275 276 /* verify that we won't overflow size_t in malloc() */ 277 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); 284 free(memchunk); 285 return -5; 286 } 287 288 /* allocate array for file descriptors */ 289 290 do { 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)); 294 if(!fd) { 295 fprintf(stderr, "fd, malloc() failed\n"); 296 num_open.rlim_max /= 2; 297 } 298 } while(num_open.rlim_max && !fd); 299 if(!fd) { 300 store_errmsg("fd, malloc() failed", ERRNO); 301 fprintf(stderr, "%s\n", msgbuff); 302 free(memchunk); 303 return -6; 304 } 305 306 /* initialize it to fight lazy allocation */ 307 308 fprintf(stderr, "initializing fd array\n"); 309 310 for(num_open.rlim_cur = 0; 311 num_open.rlim_cur < num_open.rlim_max; 312 num_open.rlim_cur++) 313 fd[num_open.rlim_cur] = -1; 314 315 snprintf(strbuff, sizeof(strbuff), fmt, num_open.rlim_max); 316 fprintf(stderr, "trying to open %s file descriptors\n", strbuff); 317 318 /* open a dummy descriptor */ 319 320 fd[0] = open(DEV_NULL, O_RDONLY); 321 if(fd[0] < 0) { 322 snprintf(strbuff, sizeof(strbuff), "opening of %s failed", DEV_NULL); 323 store_errmsg(strbuff, ERRNO); 324 fprintf(stderr, "%s\n", msgbuff); 325 free(fd); 326 fd = NULL; 327 free(memchunk); 328 return -7; 329 } 330 331 /* create a bunch of file descriptors */ 332 333 for(num_open.rlim_cur = 1; 334 num_open.rlim_cur < num_open.rlim_max; 335 num_open.rlim_cur++) { 336 337 fd[num_open.rlim_cur] = dup(fd[0]); 338 339 if(fd[num_open.rlim_cur] < 0) { 340 341 fd[num_open.rlim_cur] = -1; 342 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); 346 347 snprintf(strbuff1, sizeof(strbuff1), fmt, num_open.rlim_cur); 348 snprintf(strbuff, sizeof(strbuff), "fds system limit seems close to %s", 349 strbuff1); 350 fprintf(stderr, "%s\n", strbuff); 351 352 num_open.rlim_max = num_open.rlim_cur - SAFETY_MARGIN; 353 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", 357 strbuff1); 358 fprintf(stderr, "%s\n", strbuff); 359 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; 365 } 366 367 snprintf(strbuff, sizeof(strbuff), fmt, num_open.rlim_max); 368 fprintf(stderr, "shrinking array for %s file descriptors\n", strbuff); 369 370 /* we don't care if we can't shrink it */ 371 372 tmpfd = realloc(fd, sizeof(*fd) * (size_t)(num_open.rlim_max)); 373 if(tmpfd) { 374 fd = tmpfd; 375 tmpfd = NULL; 376 } 377 378 break; 379 380 } 381 382 } 383 384 snprintf(strbuff, sizeof(strbuff), fmt, num_open.rlim_max); 385 fprintf(stderr, "%s file descriptors open\n", strbuff); 386 387 #if !defined(HAVE_POLL_FINE) && \ 388 !defined(USE_WINSOCK) && \ 389 !defined(TPF) 390 391 /* 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. 400 */ 401 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", 405 FD_SETSIZE); 406 store_errmsg(strbuff, 0); 407 fprintf(stderr, "%s\n", msgbuff); 408 close_file_descriptors(); 409 free(memchunk); 410 return -8; 411 } 412 413 num_open.rlim_cur = FD_SETSIZE - SAFETY_MARGIN; 414 for(rl.rlim_cur = 0; 415 rl.rlim_cur < num_open.rlim_max; 416 rl.rlim_cur++) { 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", 420 FD_SETSIZE); 421 store_errmsg(strbuff, 0); 422 fprintf(stderr, "%s\n", msgbuff); 423 close_file_descriptors(); 424 free(memchunk); 425 return -9; 426 } 427 } 428 429 #endif /* using a FD_SETSIZE bound select() */ 430 431 /* 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. 438 */ 439 440 if(!fopen_works()) { 441 snprintf(strbuff1, sizeof(strbuff1), fmt, num_open.rlim_max); 442 snprintf(strbuff, sizeof(strbuff), "fopen fails with %s fds open", 443 strbuff1); 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(); 448 free(memchunk); 449 return -10; 450 } 451 452 /* free the chunk of memory we were reserving so that it 453 becomes becomes available to the test */ 454 455 free(memchunk); 456 457 /* close file descriptors unless instructed to keep them */ 458 459 if(!keep_open) { 460 close_file_descriptors(); 461 } 462 463 return 0; 464 } 465 466 int test(char *URL) 467 { 468 CURLcode res; 469 CURL *curl; 470 471 if(!strcmp(URL, "check")) { 472 /* used by the test script to ask if we can run this test or not */ 473 if(rlimit(FALSE)) { 474 fprintf(stdout, "rlimit problem: %s\n", msgbuff); 475 return 1; 476 } 477 return 0; /* sure, run this! */ 478 } 479 480 if(rlimit(TRUE)) { 481 /* failure */ 482 return TEST_ERR_MAJOR_BAD; 483 } 484 485 /* run the test with the bunch of open file descriptors 486 and close them all once the test is over */ 487 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; 492 } 493 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; 499 } 500 501 test_setopt(curl, CURLOPT_URL, URL); 502 test_setopt(curl, CURLOPT_HEADER, 1L); 503 504 res = curl_easy_perform(curl); 505 506 test_cleanup: 507 508 close_file_descriptors(); 509 curl_easy_cleanup(curl); 510 curl_global_cleanup(); 511 512 return (int)res; 513 } 514 515 #else /* defined(HAVE_GETRLIMIT) && defined(HAVE_SETRLIMIT) */ 516 517 int test(char *URL) 518 { 519 (void)URL; 520 printf("system lacks necessary system function(s)"); 521 return 1; /* skip test */ 522 } 523 524 #endif /* defined(HAVE_GETRLIMIT) && defined(HAVE_SETRLIMIT) */ 525