Home | History | Annotate | Download | only in libtest
      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