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 #include <limits.h> 31 32 #include "warnless.h" 33 #include "memdebug.h" 34 35 #if !defined(HAVE_POLL_FINE) && \ 36 !defined(USE_WINSOCK) && \ 37 !defined(TPF) && \ 38 !defined(FD_SETSIZE) 39 #error "this test requires FD_SETSIZE" 40 #endif 41 42 #define SAFETY_MARGIN (11) 43 44 #if defined(WIN32) || defined(_WIN32) || defined(MSDOS) 45 #define DEV_NULL "NUL" 46 #else 47 #define DEV_NULL "/dev/null" 48 #endif 49 50 #if defined(HAVE_GETRLIMIT) && defined(HAVE_SETRLIMIT) 51 52 static int *fd = NULL; 53 static struct rlimit num_open; 54 static char msgbuff[256]; 55 56 static void store_errmsg(const char *msg, int err) 57 { 58 if(!err) 59 snprintf(msgbuff, sizeof(msgbuff), "%s", msg); 60 else 61 snprintf(msgbuff, sizeof(msgbuff), "%s, errno %d, %s", msg, err, 62 strerror(err)); 63 } 64 65 static void close_file_descriptors(void) 66 { 67 for(num_open.rlim_cur = 0; 68 num_open.rlim_cur < num_open.rlim_max; 69 num_open.rlim_cur++) 70 if(fd[num_open.rlim_cur] > 0) 71 close(fd[num_open.rlim_cur]); 72 free(fd); 73 fd = NULL; 74 } 75 76 static int fopen_works(void) 77 { 78 FILE *fpa[3]; 79 int i; 80 int ret = 1; 81 82 for(i = 0; i < 3; i++) { 83 fpa[i] = NULL; 84 } 85 for(i = 0; i < 3; i++) { 86 fpa[i] = fopen(DEV_NULL, FOPEN_READTEXT); 87 if(fpa[i] == NULL) { 88 store_errmsg("fopen failed", errno); 89 fprintf(stderr, "%s\n", msgbuff); 90 ret = 0; 91 break; 92 } 93 } 94 for(i = 0; i < 3; i++) { 95 if(fpa[i] != NULL) 96 fclose(fpa[i]); 97 } 98 return ret; 99 } 100 101 static int rlimit(int keep_open) 102 { 103 int *tmpfd; 104 rlim_t nitems, i; 105 int *memchunk = NULL; 106 char *fmt; 107 struct rlimit rl; 108 char strbuff[256]; 109 char strbuff1[81]; 110 char fmt_u[] = "%u"; 111 char fmt_lu[] = "%lu"; 112 #ifdef HAVE_LONGLONG 113 char fmt_llu[] = "%llu"; 114 115 if(sizeof(rl.rlim_max) > sizeof(long)) 116 fmt = fmt_llu; 117 else 118 #endif 119 fmt = (sizeof(rl.rlim_max) < sizeof(long))?fmt_u:fmt_lu; 120 121 /* get initial open file limits */ 122 123 if(getrlimit(RLIMIT_NOFILE, &rl) != 0) { 124 store_errmsg("getrlimit() failed", errno); 125 fprintf(stderr, "%s\n", msgbuff); 126 return -1; 127 } 128 129 /* show initial open file limits */ 130 131 #ifdef RLIM_INFINITY 132 if(rl.rlim_cur == RLIM_INFINITY) 133 strcpy(strbuff, "INFINITY"); 134 else 135 #endif 136 snprintf(strbuff, sizeof(strbuff), fmt, rl.rlim_cur); 137 fprintf(stderr, "initial soft limit: %s\n", strbuff); 138 139 #ifdef RLIM_INFINITY 140 if(rl.rlim_max == RLIM_INFINITY) 141 strcpy(strbuff, "INFINITY"); 142 else 143 #endif 144 snprintf(strbuff, sizeof(strbuff), fmt, rl.rlim_max); 145 fprintf(stderr, "initial hard limit: %s\n", strbuff); 146 147 /* 148 * if soft limit and hard limit are different we ask the 149 * system to raise soft limit all the way up to the hard 150 * limit. Due to some other system limit the soft limit 151 * might not be raised up to the hard limit. So from this 152 * point the resulting soft limit is our limit. Trying to 153 * open more than soft limit file descriptors will fail. 154 */ 155 156 if(rl.rlim_cur != rl.rlim_max) { 157 158 #ifdef OPEN_MAX 159 if((rl.rlim_cur > 0) && 160 (rl.rlim_cur < OPEN_MAX)) { 161 fprintf(stderr, "raising soft limit up to OPEN_MAX\n"); 162 rl.rlim_cur = OPEN_MAX; 163 if(setrlimit(RLIMIT_NOFILE, &rl) != 0) { 164 /* on failure don't abort just issue a warning */ 165 store_errmsg("setrlimit() failed", errno); 166 fprintf(stderr, "%s\n", msgbuff); 167 msgbuff[0] = '\0'; 168 } 169 } 170 #endif 171 172 fprintf(stderr, "raising soft limit up to hard limit\n"); 173 rl.rlim_cur = rl.rlim_max; 174 if(setrlimit(RLIMIT_NOFILE, &rl) != 0) { 175 /* on failure don't abort just issue a warning */ 176 store_errmsg("setrlimit() failed", errno); 177 fprintf(stderr, "%s\n", msgbuff); 178 msgbuff[0] = '\0'; 179 } 180 181 /* get current open file limits */ 182 183 if(getrlimit(RLIMIT_NOFILE, &rl) != 0) { 184 store_errmsg("getrlimit() failed", errno); 185 fprintf(stderr, "%s\n", msgbuff); 186 return -3; 187 } 188 189 /* show current open file limits */ 190 191 #ifdef RLIM_INFINITY 192 if(rl.rlim_cur == RLIM_INFINITY) 193 strcpy(strbuff, "INFINITY"); 194 else 195 #endif 196 snprintf(strbuff, sizeof(strbuff), fmt, rl.rlim_cur); 197 fprintf(stderr, "current soft limit: %s\n", strbuff); 198 199 #ifdef RLIM_INFINITY 200 if(rl.rlim_max == RLIM_INFINITY) 201 strcpy(strbuff, "INFINITY"); 202 else 203 #endif 204 snprintf(strbuff, sizeof(strbuff), fmt, rl.rlim_max); 205 fprintf(stderr, "current hard limit: %s\n", strbuff); 206 207 } /* (rl.rlim_cur != rl.rlim_max) */ 208 209 /* 210 * test 537 is all about testing libcurl functionality 211 * when the system has nearly exhausted the number of 212 * available file descriptors. Test 537 will try to run 213 * with a very small number of file descriptors available. 214 * This implies that any file descriptor which is open 215 * when the test runs will have a number in the high range 216 * of whatever the system supports. 217 */ 218 219 /* 220 * reserve a chunk of memory before opening file descriptors to 221 * avoid a low memory condition once the file descriptors are 222 * open. System conditions that could make the test fail should 223 * be addressed in the precheck phase. This chunk of memory shall 224 * be always free()ed before exiting the rlimit() function so 225 * that it becomes available to the test. 226 */ 227 228 for(nitems = i = 1; nitems <= i; i *= 2) 229 nitems = i; 230 if(nitems > 0x7fff) 231 nitems = 0x40000; 232 do { 233 num_open.rlim_max = sizeof(*memchunk) * nitems; 234 snprintf(strbuff, sizeof(strbuff), fmt, num_open.rlim_max); 235 fprintf(stderr, "allocating memchunk %s byte array\n", strbuff); 236 memchunk = malloc(sizeof(*memchunk) * (size_t)nitems); 237 if(!memchunk) { 238 fprintf(stderr, "memchunk, malloc() failed\n"); 239 nitems /= 2; 240 } 241 } while(nitems && !memchunk); 242 if(!memchunk) { 243 store_errmsg("memchunk, malloc() failed", errno); 244 fprintf(stderr, "%s\n", msgbuff); 245 return -4; 246 } 247 248 /* initialize it to fight lazy allocation */ 249 250 fprintf(stderr, "initializing memchunk array\n"); 251 252 for(i = 0; i < nitems; i++) 253 memchunk[i] = -1; 254 255 /* set the number of file descriptors we will try to open */ 256 257 #ifdef RLIM_INFINITY 258 if((rl.rlim_cur > 0) && (rl.rlim_cur != RLIM_INFINITY)) { 259 #else 260 if(rl.rlim_cur > 0) { 261 #endif 262 /* soft limit minus SAFETY_MARGIN */ 263 num_open.rlim_max = rl.rlim_cur - SAFETY_MARGIN; 264 } 265 else { 266 /* a huge number of file descriptors */ 267 for(nitems = i = 1; nitems <= i; i *= 2) 268 nitems = i; 269 if(nitems > 0x7fff) 270 nitems = 0x40000; 271 num_open.rlim_max = nitems; 272 } 273 274 /* verify that we won't overflow size_t in malloc() */ 275 276 if((size_t)(num_open.rlim_max) > ((size_t)-1) / sizeof(*fd)) { 277 snprintf(strbuff1, sizeof(strbuff1), fmt, num_open.rlim_max); 278 snprintf(strbuff, sizeof(strbuff), "unable to allocate an array for %s " 279 "file descriptors, would overflow size_t", strbuff1); 280 store_errmsg(strbuff, 0); 281 fprintf(stderr, "%s\n", msgbuff); 282 free(memchunk); 283 return -5; 284 } 285 286 /* allocate array for file descriptors */ 287 288 do { 289 snprintf(strbuff, sizeof(strbuff), fmt, num_open.rlim_max); 290 fprintf(stderr, "allocating array for %s file descriptors\n", strbuff); 291 fd = malloc(sizeof(*fd) * (size_t)(num_open.rlim_max)); 292 if(!fd) { 293 fprintf(stderr, "fd, malloc() failed\n"); 294 num_open.rlim_max /= 2; 295 } 296 } while(num_open.rlim_max && !fd); 297 if(!fd) { 298 store_errmsg("fd, malloc() failed", errno); 299 fprintf(stderr, "%s\n", msgbuff); 300 free(memchunk); 301 return -6; 302 } 303 304 /* initialize it to fight lazy allocation */ 305 306 fprintf(stderr, "initializing fd array\n"); 307 308 for(num_open.rlim_cur = 0; 309 num_open.rlim_cur < num_open.rlim_max; 310 num_open.rlim_cur++) 311 fd[num_open.rlim_cur] = -1; 312 313 snprintf(strbuff, sizeof(strbuff), fmt, num_open.rlim_max); 314 fprintf(stderr, "trying to open %s file descriptors\n", strbuff); 315 316 /* open a dummy descriptor */ 317 318 fd[0] = open(DEV_NULL, O_RDONLY); 319 if(fd[0] < 0) { 320 snprintf(strbuff, sizeof(strbuff), "opening of %s failed", DEV_NULL); 321 store_errmsg(strbuff, errno); 322 fprintf(stderr, "%s\n", msgbuff); 323 free(fd); 324 fd = NULL; 325 free(memchunk); 326 return -7; 327 } 328 329 /* create a bunch of file descriptors */ 330 331 for(num_open.rlim_cur = 1; 332 num_open.rlim_cur < num_open.rlim_max; 333 num_open.rlim_cur++) { 334 335 fd[num_open.rlim_cur] = dup(fd[0]); 336 337 if(fd[num_open.rlim_cur] < 0) { 338 339 fd[num_open.rlim_cur] = -1; 340 341 snprintf(strbuff1, sizeof(strbuff1), fmt, num_open.rlim_cur); 342 snprintf(strbuff, sizeof(strbuff), "dup() attempt %s failed", strbuff1); 343 fprintf(stderr, "%s\n", strbuff); 344 345 snprintf(strbuff1, sizeof(strbuff1), fmt, num_open.rlim_cur); 346 snprintf(strbuff, sizeof(strbuff), "fds system limit seems close to %s", 347 strbuff1); 348 fprintf(stderr, "%s\n", strbuff); 349 350 num_open.rlim_max = num_open.rlim_cur - SAFETY_MARGIN; 351 352 num_open.rlim_cur -= num_open.rlim_max; 353 snprintf(strbuff1, sizeof(strbuff1), fmt, num_open.rlim_cur); 354 snprintf(strbuff, sizeof(strbuff), "closing %s file descriptors", 355 strbuff1); 356 fprintf(stderr, "%s\n", strbuff); 357 358 for(num_open.rlim_cur = num_open.rlim_max; 359 fd[num_open.rlim_cur] >= 0; 360 num_open.rlim_cur++) { 361 close(fd[num_open.rlim_cur]); 362 fd[num_open.rlim_cur] = -1; 363 } 364 365 snprintf(strbuff, sizeof(strbuff), fmt, num_open.rlim_max); 366 fprintf(stderr, "shrinking array for %s file descriptors\n", strbuff); 367 368 /* we don't care if we can't shrink it */ 369 370 tmpfd = realloc(fd, sizeof(*fd) * (size_t)(num_open.rlim_max)); 371 if(tmpfd) { 372 fd = tmpfd; 373 tmpfd = NULL; 374 } 375 376 break; 377 378 } 379 380 } 381 382 snprintf(strbuff, sizeof(strbuff), fmt, num_open.rlim_max); 383 fprintf(stderr, "%s file descriptors open\n", strbuff); 384 385 #if !defined(HAVE_POLL_FINE) && \ 386 !defined(USE_WINSOCK) && \ 387 !defined(TPF) 388 389 /* 390 * when using select() instead of poll() we cannot test 391 * libcurl functionality with a socket number equal or 392 * greater than FD_SETSIZE. In any case, macro VERIFY_SOCK 393 * in lib/select.c enforces this check and protects libcurl 394 * from a possible crash. The effect of this protection 395 * is that test 537 will always fail, since the actual 396 * call to select() never takes place. We skip test 537 397 * with an indication that select limit would be exceeded. 398 */ 399 400 num_open.rlim_cur = FD_SETSIZE - SAFETY_MARGIN; 401 if(num_open.rlim_max > num_open.rlim_cur) { 402 snprintf(strbuff, sizeof(strbuff), "select limit is FD_SETSIZE %d", 403 FD_SETSIZE); 404 store_errmsg(strbuff, 0); 405 fprintf(stderr, "%s\n", msgbuff); 406 close_file_descriptors(); 407 free(memchunk); 408 return -8; 409 } 410 411 num_open.rlim_cur = FD_SETSIZE - SAFETY_MARGIN; 412 for(rl.rlim_cur = 0; 413 rl.rlim_cur < num_open.rlim_max; 414 rl.rlim_cur++) { 415 if((fd[rl.rlim_cur] > 0) && 416 ((unsigned int)fd[rl.rlim_cur] > num_open.rlim_cur)) { 417 snprintf(strbuff, sizeof(strbuff), "select limit is FD_SETSIZE %d", 418 FD_SETSIZE); 419 store_errmsg(strbuff, 0); 420 fprintf(stderr, "%s\n", msgbuff); 421 close_file_descriptors(); 422 free(memchunk); 423 return -9; 424 } 425 } 426 427 #endif /* using a FD_SETSIZE bound select() */ 428 429 /* 430 * Old or 'backwards compatible' implementations of stdio do not allow 431 * handling of streams with an underlying file descriptor number greater 432 * than 255, even when allowing high numbered file descriptors for sockets. 433 * At this point we have a big number of file descriptors which have been 434 * opened using dup(), so lets test the stdio implementation and discover 435 * if it is capable of fopen()ing some additional files. 436 */ 437 438 if(!fopen_works()) { 439 snprintf(strbuff1, sizeof(strbuff1), fmt, num_open.rlim_max); 440 snprintf(strbuff, sizeof(strbuff), "fopen fails with %s fds open", 441 strbuff1); 442 fprintf(stderr, "%s\n", msgbuff); 443 snprintf(strbuff, sizeof(strbuff), "fopen fails with lots of fds open"); 444 store_errmsg(strbuff, 0); 445 close_file_descriptors(); 446 free(memchunk); 447 return -10; 448 } 449 450 /* free the chunk of memory we were reserving so that it 451 becomes becomes available to the test */ 452 453 free(memchunk); 454 455 /* close file descriptors unless instructed to keep them */ 456 457 if(!keep_open) { 458 close_file_descriptors(); 459 } 460 461 return 0; 462 } 463 464 int test(char *URL) 465 { 466 CURLcode res; 467 CURL *curl; 468 469 if(!strcmp(URL, "check")) { 470 /* used by the test script to ask if we can run this test or not */ 471 if(rlimit(FALSE)) { 472 fprintf(stdout, "rlimit problem: %s\n", msgbuff); 473 return 1; 474 } 475 return 0; /* sure, run this! */ 476 } 477 478 if(rlimit(TRUE)) { 479 /* failure */ 480 return TEST_ERR_MAJOR_BAD; 481 } 482 483 /* run the test with the bunch of open file descriptors 484 and close them all once the test is over */ 485 486 if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { 487 fprintf(stderr, "curl_global_init() failed\n"); 488 close_file_descriptors(); 489 return TEST_ERR_MAJOR_BAD; 490 } 491 492 curl = curl_easy_init(); 493 if(!curl) { 494 fprintf(stderr, "curl_easy_init() failed\n"); 495 close_file_descriptors(); 496 curl_global_cleanup(); 497 return TEST_ERR_MAJOR_BAD; 498 } 499 500 test_setopt(curl, CURLOPT_URL, URL); 501 test_setopt(curl, CURLOPT_HEADER, 1L); 502 503 res = curl_easy_perform(curl); 504 505 test_cleanup: 506 507 close_file_descriptors(); 508 curl_easy_cleanup(curl); 509 curl_global_cleanup(); 510 511 return (int)res; 512 } 513 514 #else /* defined(HAVE_GETRLIMIT) && defined(HAVE_SETRLIMIT) */ 515 516 int test(char *URL) 517 { 518 (void)URL; 519 printf("system lacks necessary system function(s)"); 520 return 1; /* skip test */ 521 } 522 523 #endif /* defined(HAVE_GETRLIMIT) && defined(HAVE_SETRLIMIT) */ 524