00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "test.h"
00023
00024 #ifdef HAVE_SYS_RESOURCE_H
00025 #include <sys/resource.h>
00026 #endif
00027 #ifdef HAVE_FCNTL_H
00028 #include <fcntl.h>
00029 #endif
00030 #ifdef HAVE_LIMITS_H
00031 #include <limits.h>
00032 #endif
00033
00034 #include "warnless.h"
00035 #include "memdebug.h"
00036
00037 #ifndef FD_SETSIZE
00038 #error "this test requires FD_SETSIZE"
00039 #endif
00040
00041 #define SAFETY_MARGIN (16)
00042 #define NUM_OPEN (FD_SETSIZE + 10)
00043 #define NUM_NEEDED (NUM_OPEN + SAFETY_MARGIN)
00044
00045 #if defined(WIN32) || defined(_WIN32) || defined(MSDOS)
00046 #define DEV_NULL "NUL"
00047 #else
00048 #define DEV_NULL "/dev/null"
00049 #endif
00050
00051 #if defined(HAVE_GETRLIMIT) && defined(HAVE_SETRLIMIT)
00052
00053 static int *fd = NULL;
00054 static struct rlimit num_open;
00055 static char msgbuff[256];
00056
00057 static void store_errmsg(const char *msg, int err)
00058 {
00059 if(!err)
00060 snprintf(msgbuff, sizeof(msgbuff), "%s", msg);
00061 else
00062 snprintf(msgbuff, sizeof(msgbuff), "%s, errno %d, %s", msg,
00063 err, strerror(err));
00064 }
00065
00066 static void close_file_descriptors(void)
00067 {
00068 for(num_open.rlim_cur = 0;
00069 num_open.rlim_cur < num_open.rlim_max;
00070 num_open.rlim_cur++)
00071 if(fd[num_open.rlim_cur] > 0)
00072 close(fd[num_open.rlim_cur]);
00073 free(fd);
00074 fd = NULL;
00075 }
00076
00077 static int fopen_works(void)
00078 {
00079 FILE *fpa[3];
00080 int i;
00081 int ret = 1;
00082
00083 for(i = 0; i < 3; i++) {
00084 fpa[i] = NULL;
00085 }
00086 for(i = 0; i < 3; i++) {
00087 fpa[i] = fopen(DEV_NULL, FOPEN_READTEXT);
00088 if(fpa[i] == NULL) {
00089 store_errmsg("fopen failed", ERRNO);
00090 fprintf(stderr, "%s\n", msgbuff);
00091 ret = 0;
00092 break;
00093 }
00094 }
00095 for(i = 0; i < 3; i++) {
00096 if(fpa[i] != NULL)
00097 fclose(fpa[i]);
00098 }
00099 return ret;
00100 }
00101
00102 static int rlimit(int keep_open)
00103 {
00104 int nitems, i;
00105 int *memchunk = NULL;
00106 char *fmt;
00107 struct rlimit rl;
00108 char strbuff[256];
00109 char strbuff1[81];
00110 char strbuff2[81];
00111 char fmt_u[] = "%u";
00112 char fmt_lu[] = "%lu";
00113 #ifdef HAVE_LONGLONG
00114 char fmt_llu[] = "%llu";
00115
00116 if(sizeof(rl.rlim_max) > sizeof(long))
00117 fmt = fmt_llu;
00118 else
00119 #endif
00120 fmt = (sizeof(rl.rlim_max) < sizeof(long))?fmt_u:fmt_lu;
00121
00122
00123
00124 if(getrlimit(RLIMIT_NOFILE, &rl) != 0) {
00125 store_errmsg("getrlimit() failed", ERRNO);
00126 fprintf(stderr, "%s\n", msgbuff);
00127 return -1;
00128 }
00129
00130
00131
00132 #ifdef RLIM_INFINITY
00133 if(rl.rlim_cur == RLIM_INFINITY)
00134 strcpy(strbuff, "INFINITY");
00135 else
00136 #endif
00137 snprintf(strbuff, sizeof(strbuff), fmt, rl.rlim_cur);
00138 fprintf(stderr, "initial soft limit: %s\n", strbuff);
00139
00140 #ifdef RLIM_INFINITY
00141 if(rl.rlim_max == RLIM_INFINITY)
00142 strcpy(strbuff, "INFINITY");
00143 else
00144 #endif
00145 snprintf(strbuff, sizeof(strbuff), fmt, rl.rlim_max);
00146 fprintf(stderr, "initial hard limit: %s\n", strbuff);
00147
00148
00149
00150 fprintf(stderr, "test518 FD_SETSIZE: %d\n", FD_SETSIZE);
00151 fprintf(stderr, "test518 NUM_OPEN : %d\n", NUM_OPEN);
00152 fprintf(stderr, "test518 NUM_NEEDED: %d\n", NUM_NEEDED);
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163 if(rl.rlim_cur != rl.rlim_max) {
00164
00165 #ifdef OPEN_MAX
00166 if((rl.rlim_cur > 0) &&
00167 (rl.rlim_cur < OPEN_MAX)) {
00168 fprintf(stderr, "raising soft limit up to OPEN_MAX\n");
00169 rl.rlim_cur = OPEN_MAX;
00170 if(setrlimit(RLIMIT_NOFILE, &rl) != 0) {
00171
00172 store_errmsg("setrlimit() failed", ERRNO);
00173 fprintf(stderr, "%s\n", msgbuff);
00174 msgbuff[0] = '\0';
00175 }
00176 }
00177 #endif
00178
00179 fprintf(stderr, "raising soft limit up to hard limit\n");
00180 rl.rlim_cur = rl.rlim_max;
00181 if(setrlimit(RLIMIT_NOFILE, &rl) != 0) {
00182
00183 store_errmsg("setrlimit() failed", ERRNO);
00184 fprintf(stderr, "%s\n", msgbuff);
00185 msgbuff[0] = '\0';
00186 }
00187
00188
00189
00190 if(getrlimit(RLIMIT_NOFILE, &rl) != 0) {
00191 store_errmsg("getrlimit() failed", ERRNO);
00192 fprintf(stderr, "%s\n", msgbuff);
00193 return -3;
00194 }
00195
00196
00197
00198 #ifdef RLIM_INFINITY
00199 if(rl.rlim_cur == RLIM_INFINITY)
00200 strcpy(strbuff, "INFINITY");
00201 else
00202 #endif
00203 snprintf(strbuff, sizeof(strbuff), fmt, rl.rlim_cur);
00204 fprintf(stderr, "current soft limit: %s\n", strbuff);
00205
00206 #ifdef RLIM_INFINITY
00207 if(rl.rlim_max == RLIM_INFINITY)
00208 strcpy(strbuff, "INFINITY");
00209 else
00210 #endif
00211 snprintf(strbuff, sizeof(strbuff), fmt, rl.rlim_max);
00212 fprintf(stderr, "current hard limit: %s\n", strbuff);
00213
00214 }
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231 num_open.rlim_cur = NUM_NEEDED;
00232
00233 if((rl.rlim_cur > 0) &&
00234 #ifdef RLIM_INFINITY
00235 (rl.rlim_cur != RLIM_INFINITY) &&
00236 #endif
00237 (rl.rlim_cur <= num_open.rlim_cur)) {
00238 snprintf(strbuff2, sizeof(strbuff2), fmt, rl.rlim_cur);
00239 snprintf(strbuff1, sizeof(strbuff1), fmt, num_open.rlim_cur);
00240 snprintf(strbuff, sizeof(strbuff), "fds needed %s > system limit %s",
00241 strbuff1, strbuff2);
00242 store_errmsg(strbuff, 0);
00243 fprintf(stderr, "%s\n", msgbuff);
00244 return -4;
00245 }
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256 for(nitems = i = 1; nitems <= i; i *= 2)
00257 nitems = i;
00258 if(nitems > 0x7fff)
00259 nitems = 0x40000;
00260 do {
00261 num_open.rlim_max = sizeof(*memchunk) * (size_t)nitems;
00262 snprintf(strbuff, sizeof(strbuff), fmt, num_open.rlim_max);
00263 fprintf(stderr, "allocating memchunk %s byte array\n", strbuff);
00264 memchunk = malloc(sizeof(*memchunk) * (size_t)nitems);
00265 if(!memchunk) {
00266 fprintf(stderr, "memchunk, malloc() failed\n");
00267 nitems /= 2;
00268 }
00269 } while(nitems && !memchunk);
00270 if(!memchunk) {
00271 store_errmsg("memchunk, malloc() failed", ERRNO);
00272 fprintf(stderr, "%s\n", msgbuff);
00273 return -5;
00274 }
00275
00276
00277
00278 fprintf(stderr, "initializing memchunk array\n");
00279
00280 for(i = 0; i < nitems; i++)
00281 memchunk[i] = -1;
00282
00283
00284
00285 num_open.rlim_max = NUM_OPEN;
00286
00287
00288
00289 if((size_t)(num_open.rlim_max) > ((size_t)-1) / sizeof(*fd)) {
00290 snprintf(strbuff1, sizeof(strbuff1), fmt, num_open.rlim_max);
00291 snprintf(strbuff, sizeof(strbuff), "unable to allocate an array for %s "
00292 "file descriptors, would overflow size_t", strbuff1);
00293 store_errmsg(strbuff, 0);
00294 fprintf(stderr, "%s\n", msgbuff);
00295 free(memchunk);
00296 return -6;
00297 }
00298
00299
00300
00301 snprintf(strbuff, sizeof(strbuff), fmt, num_open.rlim_max);
00302 fprintf(stderr, "allocating array for %s file descriptors\n", strbuff);
00303
00304 fd = malloc(sizeof(*fd) * (size_t)(num_open.rlim_max));
00305 if(!fd) {
00306 store_errmsg("fd, malloc() failed", ERRNO);
00307 fprintf(stderr, "%s\n", msgbuff);
00308 free(memchunk);
00309 return -7;
00310 }
00311
00312
00313
00314 fprintf(stderr, "initializing fd array\n");
00315
00316 for(num_open.rlim_cur = 0;
00317 num_open.rlim_cur < num_open.rlim_max;
00318 num_open.rlim_cur++)
00319 fd[num_open.rlim_cur] = -1;
00320
00321 snprintf(strbuff, sizeof(strbuff), fmt, num_open.rlim_max);
00322 fprintf(stderr, "trying to open %s file descriptors\n", strbuff);
00323
00324
00325
00326 fd[0] = open(DEV_NULL, O_RDONLY);
00327 if(fd[0] < 0) {
00328 snprintf(strbuff, sizeof(strbuff), "opening of %s failed", DEV_NULL);
00329 store_errmsg(strbuff, ERRNO);
00330 fprintf(stderr, "%s\n", msgbuff);
00331 free(fd);
00332 fd = NULL;
00333 free(memchunk);
00334 return -8;
00335 }
00336
00337
00338
00339 for(num_open.rlim_cur = 1;
00340 num_open.rlim_cur < num_open.rlim_max;
00341 num_open.rlim_cur++) {
00342
00343 fd[num_open.rlim_cur] = dup(fd[0]);
00344
00345 if(fd[num_open.rlim_cur] < 0) {
00346
00347 fd[num_open.rlim_cur] = -1;
00348
00349 snprintf(strbuff1, sizeof(strbuff1), fmt, num_open.rlim_cur);
00350 snprintf(strbuff, sizeof(strbuff), "dup() attempt %s failed", strbuff1);
00351 fprintf(stderr, "%s\n", strbuff);
00352
00353 snprintf(strbuff1, sizeof(strbuff), fmt, num_open.rlim_cur);
00354 snprintf(strbuff, sizeof(strbuff), "fds system limit seems close to %s",
00355 strbuff1);
00356 fprintf(stderr, "%s\n", strbuff);
00357
00358 num_open.rlim_max = NUM_NEEDED;
00359
00360 snprintf(strbuff2, sizeof(strbuff2), fmt, num_open.rlim_max);
00361 snprintf(strbuff1, sizeof(strbuff1), fmt, num_open.rlim_cur);
00362 snprintf(strbuff, sizeof(strbuff), "fds needed %s > system limit %s",
00363 strbuff2, strbuff1);
00364 store_errmsg(strbuff, 0);
00365 fprintf(stderr, "%s\n", msgbuff);
00366
00367 for(num_open.rlim_cur = 0;
00368 fd[num_open.rlim_cur] >= 0;
00369 num_open.rlim_cur++)
00370 close(fd[num_open.rlim_cur]);
00371 free(fd);
00372 fd = NULL;
00373 free(memchunk);
00374 return -9;
00375
00376 }
00377
00378 }
00379
00380 snprintf(strbuff, sizeof(strbuff), fmt, num_open.rlim_max);
00381 fprintf(stderr, "%s file descriptors open\n", strbuff);
00382
00383 #if !defined(HAVE_POLL_FINE) && \
00384 !defined(USE_WINSOCK) && \
00385 !defined(TPF)
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398 num_open.rlim_cur = FD_SETSIZE - SAFETY_MARGIN;
00399 if(num_open.rlim_max > num_open.rlim_cur) {
00400 snprintf(strbuff, sizeof(strbuff), "select limit is FD_SETSIZE %d",
00401 FD_SETSIZE);
00402 store_errmsg(strbuff, 0);
00403 fprintf(stderr, "%s\n", msgbuff);
00404 close_file_descriptors();
00405 free(memchunk);
00406 return -10;
00407 }
00408
00409 num_open.rlim_cur = FD_SETSIZE - SAFETY_MARGIN;
00410 for(rl.rlim_cur = 0;
00411 rl.rlim_cur < num_open.rlim_max;
00412 rl.rlim_cur++) {
00413 if((fd[rl.rlim_cur] > 0) &&
00414 ((unsigned int)fd[rl.rlim_cur] > num_open.rlim_cur)) {
00415 snprintf(strbuff, sizeof(strbuff), "select limit is FD_SETSIZE %d",
00416 FD_SETSIZE);
00417 store_errmsg(strbuff, 0);
00418 fprintf(stderr, "%s\n", msgbuff);
00419 close_file_descriptors();
00420 free(memchunk);
00421 return -11;
00422 }
00423 }
00424
00425 #endif
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436 if(!fopen_works()) {
00437 snprintf(strbuff1, sizeof(strbuff1), fmt, num_open.rlim_max);
00438 snprintf(strbuff, sizeof(strbuff),
00439 "fopen fails with %s fds open()",
00440 strbuff1);
00441 fprintf(stderr, "%s\n", msgbuff);
00442 snprintf(strbuff, sizeof(strbuff),
00443 "fopen fails with lots of fds open()");
00444 store_errmsg(strbuff, 0);
00445 close_file_descriptors();
00446 free(memchunk);
00447 return -12;
00448 }
00449
00450
00451
00452
00453 free(memchunk);
00454
00455
00456
00457 if(!keep_open) {
00458 close_file_descriptors();
00459 }
00460
00461 return 0;
00462 }
00463
00464 int test(char *URL)
00465 {
00466 CURLcode res;
00467 CURL *curl;
00468
00469 if(!strcmp(URL, "check")) {
00470
00471 if(rlimit(FALSE)) {
00472 fprintf(stdout, "rlimit problem: %s\n", msgbuff);
00473 return 1;
00474 }
00475 return 0;
00476 }
00477
00478 if(rlimit(TRUE)) {
00479
00480 return TEST_ERR_MAJOR_BAD;
00481 }
00482
00483
00484
00485
00486 if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
00487 fprintf(stderr, "curl_global_init() failed\n");
00488 close_file_descriptors();
00489 return TEST_ERR_MAJOR_BAD;
00490 }
00491
00492 curl = curl_easy_init();
00493 if(!curl) {
00494 fprintf(stderr, "curl_easy_init() failed\n");
00495 close_file_descriptors();
00496 curl_global_cleanup();
00497 return TEST_ERR_MAJOR_BAD;
00498 }
00499
00500 test_setopt(curl, CURLOPT_URL, URL);
00501 test_setopt(curl, CURLOPT_HEADER, 1L);
00502
00503 res = curl_easy_perform(curl);
00504
00505 test_cleanup:
00506
00507 close_file_descriptors();
00508 curl_easy_cleanup(curl);
00509 curl_global_cleanup();
00510
00511 return (int)res;
00512 }
00513
00514 #else
00515
00516 int test(char *URL)
00517 {
00518 (void)URL;
00519 printf("system lacks necessary system function(s)");
00520 return 1;
00521 }
00522
00523 #endif