113498266Sopenharmony_ci/*************************************************************************** 213498266Sopenharmony_ci * _ _ ____ _ 313498266Sopenharmony_ci * Project ___| | | | _ \| | 413498266Sopenharmony_ci * / __| | | | |_) | | 513498266Sopenharmony_ci * | (__| |_| | _ <| |___ 613498266Sopenharmony_ci * \___|\___/|_| \_\_____| 713498266Sopenharmony_ci * 813498266Sopenharmony_ci * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 913498266Sopenharmony_ci * 1013498266Sopenharmony_ci * This software is licensed as described in the file COPYING, which 1113498266Sopenharmony_ci * you should have received as part of this distribution. The terms 1213498266Sopenharmony_ci * are also available at https://curl.se/docs/copyright.html. 1313498266Sopenharmony_ci * 1413498266Sopenharmony_ci * You may opt to use, copy, modify, merge, publish, distribute and/or sell 1513498266Sopenharmony_ci * copies of the Software, and permit persons to whom the Software is 1613498266Sopenharmony_ci * furnished to do so, under the terms of the COPYING file. 1713498266Sopenharmony_ci * 1813498266Sopenharmony_ci * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 1913498266Sopenharmony_ci * KIND, either express or implied. 2013498266Sopenharmony_ci * 2113498266Sopenharmony_ci * SPDX-License-Identifier: curl 2213498266Sopenharmony_ci * 2313498266Sopenharmony_ci ***************************************************************************/ 2413498266Sopenharmony_ci#include "test.h" 2513498266Sopenharmony_ci 2613498266Sopenharmony_ci#ifdef HAVE_SYS_RESOURCE_H 2713498266Sopenharmony_ci#include <sys/resource.h> 2813498266Sopenharmony_ci#endif 2913498266Sopenharmony_ci#ifdef HAVE_FCNTL_H 3013498266Sopenharmony_ci#include <fcntl.h> 3113498266Sopenharmony_ci#endif 3213498266Sopenharmony_ci#include <limits.h> 3313498266Sopenharmony_ci 3413498266Sopenharmony_ci#include "warnless.h" 3513498266Sopenharmony_ci#include "memdebug.h" 3613498266Sopenharmony_ci 3713498266Sopenharmony_ci#if !defined(HAVE_POLL_FINE) && \ 3813498266Sopenharmony_ci !defined(USE_WINSOCK) && \ 3913498266Sopenharmony_ci !defined(FD_SETSIZE) 4013498266Sopenharmony_ci#error "this test requires FD_SETSIZE" 4113498266Sopenharmony_ci#endif 4213498266Sopenharmony_ci 4313498266Sopenharmony_ci#define SAFETY_MARGIN (11) 4413498266Sopenharmony_ci 4513498266Sopenharmony_ci#if defined(_WIN32) || defined(MSDOS) 4613498266Sopenharmony_ci#define DEV_NULL "NUL" 4713498266Sopenharmony_ci#else 4813498266Sopenharmony_ci#define DEV_NULL "/dev/null" 4913498266Sopenharmony_ci#endif 5013498266Sopenharmony_ci 5113498266Sopenharmony_ci#if defined(HAVE_GETRLIMIT) && defined(HAVE_SETRLIMIT) 5213498266Sopenharmony_ci 5313498266Sopenharmony_cistatic int *fd = NULL; 5413498266Sopenharmony_cistatic struct rlimit num_open; 5513498266Sopenharmony_cistatic char msgbuff[256]; 5613498266Sopenharmony_ci 5713498266Sopenharmony_cistatic void store_errmsg(const char *msg, int err) 5813498266Sopenharmony_ci{ 5913498266Sopenharmony_ci if(!err) 6013498266Sopenharmony_ci msnprintf(msgbuff, sizeof(msgbuff), "%s", msg); 6113498266Sopenharmony_ci else 6213498266Sopenharmony_ci msnprintf(msgbuff, sizeof(msgbuff), "%s, errno %d, %s", msg, 6313498266Sopenharmony_ci err, strerror(err)); 6413498266Sopenharmony_ci} 6513498266Sopenharmony_ci 6613498266Sopenharmony_cistatic void close_file_descriptors(void) 6713498266Sopenharmony_ci{ 6813498266Sopenharmony_ci for(num_open.rlim_cur = 0; 6913498266Sopenharmony_ci num_open.rlim_cur < num_open.rlim_max; 7013498266Sopenharmony_ci num_open.rlim_cur++) 7113498266Sopenharmony_ci if(fd[num_open.rlim_cur] > 0) 7213498266Sopenharmony_ci close(fd[num_open.rlim_cur]); 7313498266Sopenharmony_ci free(fd); 7413498266Sopenharmony_ci fd = NULL; 7513498266Sopenharmony_ci} 7613498266Sopenharmony_ci 7713498266Sopenharmony_cistatic int fopen_works(void) 7813498266Sopenharmony_ci{ 7913498266Sopenharmony_ci FILE *fpa[3]; 8013498266Sopenharmony_ci int i; 8113498266Sopenharmony_ci int ret = 1; 8213498266Sopenharmony_ci 8313498266Sopenharmony_ci for(i = 0; i < 3; i++) { 8413498266Sopenharmony_ci fpa[i] = NULL; 8513498266Sopenharmony_ci } 8613498266Sopenharmony_ci for(i = 0; i < 3; i++) { 8713498266Sopenharmony_ci fpa[i] = fopen(DEV_NULL, FOPEN_READTEXT); 8813498266Sopenharmony_ci if(!fpa[i]) { 8913498266Sopenharmony_ci store_errmsg("fopen failed", errno); 9013498266Sopenharmony_ci fprintf(stderr, "%s\n", msgbuff); 9113498266Sopenharmony_ci ret = 0; 9213498266Sopenharmony_ci break; 9313498266Sopenharmony_ci } 9413498266Sopenharmony_ci } 9513498266Sopenharmony_ci for(i = 0; i < 3; i++) { 9613498266Sopenharmony_ci if(fpa[i]) 9713498266Sopenharmony_ci fclose(fpa[i]); 9813498266Sopenharmony_ci } 9913498266Sopenharmony_ci return ret; 10013498266Sopenharmony_ci} 10113498266Sopenharmony_ci 10213498266Sopenharmony_cistatic void rlim2str(char *buf, size_t len, rlim_t val) 10313498266Sopenharmony_ci{ 10413498266Sopenharmony_ci#ifdef RLIM_INFINITY 10513498266Sopenharmony_ci if(val == RLIM_INFINITY) { 10613498266Sopenharmony_ci msnprintf(buf, len, "INFINITY"); 10713498266Sopenharmony_ci return; 10813498266Sopenharmony_ci } 10913498266Sopenharmony_ci#endif 11013498266Sopenharmony_ci#ifdef HAVE_LONGLONG 11113498266Sopenharmony_ci if(sizeof(rlim_t) > sizeof(long)) 11213498266Sopenharmony_ci msnprintf(buf, len, "%llu", (unsigned long long)val); 11313498266Sopenharmony_ci else 11413498266Sopenharmony_ci#endif 11513498266Sopenharmony_ci { 11613498266Sopenharmony_ci if(sizeof(rlim_t) < sizeof(long)) 11713498266Sopenharmony_ci msnprintf(buf, len, "%u", (unsigned int)val); 11813498266Sopenharmony_ci else 11913498266Sopenharmony_ci msnprintf(buf, len, "%lu", (unsigned long)val); 12013498266Sopenharmony_ci } 12113498266Sopenharmony_ci} 12213498266Sopenharmony_ci 12313498266Sopenharmony_cistatic int rlimit(int keep_open) 12413498266Sopenharmony_ci{ 12513498266Sopenharmony_ci int *tmpfd; 12613498266Sopenharmony_ci rlim_t nitems, i; 12713498266Sopenharmony_ci int *memchunk = NULL; 12813498266Sopenharmony_ci struct rlimit rl; 12913498266Sopenharmony_ci char strbuff[256]; 13013498266Sopenharmony_ci char strbuff1[81]; 13113498266Sopenharmony_ci 13213498266Sopenharmony_ci /* get initial open file limits */ 13313498266Sopenharmony_ci 13413498266Sopenharmony_ci if(getrlimit(RLIMIT_NOFILE, &rl) != 0) { 13513498266Sopenharmony_ci store_errmsg("getrlimit() failed", errno); 13613498266Sopenharmony_ci fprintf(stderr, "%s\n", msgbuff); 13713498266Sopenharmony_ci return -1; 13813498266Sopenharmony_ci } 13913498266Sopenharmony_ci 14013498266Sopenharmony_ci /* show initial open file limits */ 14113498266Sopenharmony_ci 14213498266Sopenharmony_ci rlim2str(strbuff, sizeof(strbuff), rl.rlim_cur); 14313498266Sopenharmony_ci fprintf(stderr, "initial soft limit: %s\n", strbuff); 14413498266Sopenharmony_ci 14513498266Sopenharmony_ci rlim2str(strbuff, sizeof(strbuff), rl.rlim_max); 14613498266Sopenharmony_ci fprintf(stderr, "initial hard limit: %s\n", strbuff); 14713498266Sopenharmony_ci 14813498266Sopenharmony_ci /* 14913498266Sopenharmony_ci * if soft limit and hard limit are different we ask the 15013498266Sopenharmony_ci * system to raise soft limit all the way up to the hard 15113498266Sopenharmony_ci * limit. Due to some other system limit the soft limit 15213498266Sopenharmony_ci * might not be raised up to the hard limit. So from this 15313498266Sopenharmony_ci * point the resulting soft limit is our limit. Trying to 15413498266Sopenharmony_ci * open more than soft limit file descriptors will fail. 15513498266Sopenharmony_ci */ 15613498266Sopenharmony_ci 15713498266Sopenharmony_ci if(rl.rlim_cur != rl.rlim_max) { 15813498266Sopenharmony_ci 15913498266Sopenharmony_ci#ifdef OPEN_MAX 16013498266Sopenharmony_ci if((rl.rlim_cur > 0) && 16113498266Sopenharmony_ci (rl.rlim_cur < OPEN_MAX)) { 16213498266Sopenharmony_ci fprintf(stderr, "raising soft limit up to OPEN_MAX\n"); 16313498266Sopenharmony_ci rl.rlim_cur = OPEN_MAX; 16413498266Sopenharmony_ci if(setrlimit(RLIMIT_NOFILE, &rl) != 0) { 16513498266Sopenharmony_ci /* on failure don't abort just issue a warning */ 16613498266Sopenharmony_ci store_errmsg("setrlimit() failed", errno); 16713498266Sopenharmony_ci fprintf(stderr, "%s\n", msgbuff); 16813498266Sopenharmony_ci msgbuff[0] = '\0'; 16913498266Sopenharmony_ci } 17013498266Sopenharmony_ci } 17113498266Sopenharmony_ci#endif 17213498266Sopenharmony_ci 17313498266Sopenharmony_ci fprintf(stderr, "raising soft limit up to hard limit\n"); 17413498266Sopenharmony_ci rl.rlim_cur = rl.rlim_max; 17513498266Sopenharmony_ci if(setrlimit(RLIMIT_NOFILE, &rl) != 0) { 17613498266Sopenharmony_ci /* on failure don't abort just issue a warning */ 17713498266Sopenharmony_ci store_errmsg("setrlimit() failed", errno); 17813498266Sopenharmony_ci fprintf(stderr, "%s\n", msgbuff); 17913498266Sopenharmony_ci msgbuff[0] = '\0'; 18013498266Sopenharmony_ci } 18113498266Sopenharmony_ci 18213498266Sopenharmony_ci /* get current open file limits */ 18313498266Sopenharmony_ci 18413498266Sopenharmony_ci if(getrlimit(RLIMIT_NOFILE, &rl) != 0) { 18513498266Sopenharmony_ci store_errmsg("getrlimit() failed", errno); 18613498266Sopenharmony_ci fprintf(stderr, "%s\n", msgbuff); 18713498266Sopenharmony_ci return -3; 18813498266Sopenharmony_ci } 18913498266Sopenharmony_ci 19013498266Sopenharmony_ci /* show current open file limits */ 19113498266Sopenharmony_ci 19213498266Sopenharmony_ci rlim2str(strbuff, sizeof(strbuff), rl.rlim_cur); 19313498266Sopenharmony_ci fprintf(stderr, "current soft limit: %s\n", strbuff); 19413498266Sopenharmony_ci 19513498266Sopenharmony_ci rlim2str(strbuff, sizeof(strbuff), rl.rlim_max); 19613498266Sopenharmony_ci fprintf(stderr, "current hard limit: %s\n", strbuff); 19713498266Sopenharmony_ci 19813498266Sopenharmony_ci } /* (rl.rlim_cur != rl.rlim_max) */ 19913498266Sopenharmony_ci 20013498266Sopenharmony_ci /* 20113498266Sopenharmony_ci * test 537 is all about testing libcurl functionality 20213498266Sopenharmony_ci * when the system has nearly exhausted the number of 20313498266Sopenharmony_ci * available file descriptors. Test 537 will try to run 20413498266Sopenharmony_ci * with a very small number of file descriptors available. 20513498266Sopenharmony_ci * This implies that any file descriptor which is open 20613498266Sopenharmony_ci * when the test runs will have a number in the high range 20713498266Sopenharmony_ci * of whatever the system supports. 20813498266Sopenharmony_ci */ 20913498266Sopenharmony_ci 21013498266Sopenharmony_ci /* 21113498266Sopenharmony_ci * reserve a chunk of memory before opening file descriptors to 21213498266Sopenharmony_ci * avoid a low memory condition once the file descriptors are 21313498266Sopenharmony_ci * open. System conditions that could make the test fail should 21413498266Sopenharmony_ci * be addressed in the precheck phase. This chunk of memory shall 21513498266Sopenharmony_ci * be always free()ed before exiting the rlimit() function so 21613498266Sopenharmony_ci * that it becomes available to the test. 21713498266Sopenharmony_ci */ 21813498266Sopenharmony_ci 21913498266Sopenharmony_ci for(nitems = i = 1; nitems <= i; i *= 2) 22013498266Sopenharmony_ci nitems = i; 22113498266Sopenharmony_ci if(nitems > 0x7fff) 22213498266Sopenharmony_ci nitems = 0x40000; 22313498266Sopenharmony_ci do { 22413498266Sopenharmony_ci num_open.rlim_max = sizeof(*memchunk) * nitems; 22513498266Sopenharmony_ci rlim2str(strbuff, sizeof(strbuff), num_open.rlim_max); 22613498266Sopenharmony_ci fprintf(stderr, "allocating memchunk %s byte array\n", strbuff); 22713498266Sopenharmony_ci memchunk = malloc(sizeof(*memchunk) * (size_t)nitems); 22813498266Sopenharmony_ci if(!memchunk) { 22913498266Sopenharmony_ci fprintf(stderr, "memchunk, malloc() failed\n"); 23013498266Sopenharmony_ci nitems /= 2; 23113498266Sopenharmony_ci } 23213498266Sopenharmony_ci } while(nitems && !memchunk); 23313498266Sopenharmony_ci if(!memchunk) { 23413498266Sopenharmony_ci store_errmsg("memchunk, malloc() failed", errno); 23513498266Sopenharmony_ci fprintf(stderr, "%s\n", msgbuff); 23613498266Sopenharmony_ci return -4; 23713498266Sopenharmony_ci } 23813498266Sopenharmony_ci 23913498266Sopenharmony_ci /* initialize it to fight lazy allocation */ 24013498266Sopenharmony_ci 24113498266Sopenharmony_ci fprintf(stderr, "initializing memchunk array\n"); 24213498266Sopenharmony_ci 24313498266Sopenharmony_ci for(i = 0; i < nitems; i++) 24413498266Sopenharmony_ci memchunk[i] = -1; 24513498266Sopenharmony_ci 24613498266Sopenharmony_ci /* set the number of file descriptors we will try to open */ 24713498266Sopenharmony_ci 24813498266Sopenharmony_ci#ifdef RLIM_INFINITY 24913498266Sopenharmony_ci if((rl.rlim_cur > 0) && (rl.rlim_cur != RLIM_INFINITY)) { 25013498266Sopenharmony_ci#else 25113498266Sopenharmony_ci if(rl.rlim_cur > 0) { 25213498266Sopenharmony_ci#endif 25313498266Sopenharmony_ci /* soft limit minus SAFETY_MARGIN */ 25413498266Sopenharmony_ci num_open.rlim_max = rl.rlim_cur - SAFETY_MARGIN; 25513498266Sopenharmony_ci } 25613498266Sopenharmony_ci else { 25713498266Sopenharmony_ci /* a huge number of file descriptors */ 25813498266Sopenharmony_ci for(nitems = i = 1; nitems <= i; i *= 2) 25913498266Sopenharmony_ci nitems = i; 26013498266Sopenharmony_ci if(nitems > 0x7fff) 26113498266Sopenharmony_ci nitems = 0x40000; 26213498266Sopenharmony_ci num_open.rlim_max = nitems; 26313498266Sopenharmony_ci } 26413498266Sopenharmony_ci 26513498266Sopenharmony_ci /* verify that we won't overflow size_t in malloc() */ 26613498266Sopenharmony_ci 26713498266Sopenharmony_ci if((size_t)(num_open.rlim_max) > ((size_t)-1) / sizeof(*fd)) { 26813498266Sopenharmony_ci rlim2str(strbuff1, sizeof(strbuff1), num_open.rlim_max); 26913498266Sopenharmony_ci msnprintf(strbuff, sizeof(strbuff), "unable to allocate an array for %s " 27013498266Sopenharmony_ci "file descriptors, would overflow size_t", strbuff1); 27113498266Sopenharmony_ci store_errmsg(strbuff, 0); 27213498266Sopenharmony_ci fprintf(stderr, "%s\n", msgbuff); 27313498266Sopenharmony_ci free(memchunk); 27413498266Sopenharmony_ci return -5; 27513498266Sopenharmony_ci } 27613498266Sopenharmony_ci 27713498266Sopenharmony_ci /* allocate array for file descriptors */ 27813498266Sopenharmony_ci 27913498266Sopenharmony_ci do { 28013498266Sopenharmony_ci rlim2str(strbuff, sizeof(strbuff), num_open.rlim_max); 28113498266Sopenharmony_ci fprintf(stderr, "allocating array for %s file descriptors\n", strbuff); 28213498266Sopenharmony_ci 28313498266Sopenharmony_ci fd = malloc(sizeof(*fd) * (size_t)(num_open.rlim_max)); 28413498266Sopenharmony_ci if(!fd) { 28513498266Sopenharmony_ci fprintf(stderr, "fd, malloc() failed\n"); 28613498266Sopenharmony_ci num_open.rlim_max /= 2; 28713498266Sopenharmony_ci } 28813498266Sopenharmony_ci } while(num_open.rlim_max && !fd); 28913498266Sopenharmony_ci if(!fd) { 29013498266Sopenharmony_ci store_errmsg("fd, malloc() failed", errno); 29113498266Sopenharmony_ci fprintf(stderr, "%s\n", msgbuff); 29213498266Sopenharmony_ci free(memchunk); 29313498266Sopenharmony_ci return -6; 29413498266Sopenharmony_ci } 29513498266Sopenharmony_ci 29613498266Sopenharmony_ci /* initialize it to fight lazy allocation */ 29713498266Sopenharmony_ci 29813498266Sopenharmony_ci fprintf(stderr, "initializing fd array\n"); 29913498266Sopenharmony_ci 30013498266Sopenharmony_ci for(num_open.rlim_cur = 0; 30113498266Sopenharmony_ci num_open.rlim_cur < num_open.rlim_max; 30213498266Sopenharmony_ci num_open.rlim_cur++) 30313498266Sopenharmony_ci fd[num_open.rlim_cur] = -1; 30413498266Sopenharmony_ci 30513498266Sopenharmony_ci rlim2str(strbuff, sizeof(strbuff), num_open.rlim_max); 30613498266Sopenharmony_ci fprintf(stderr, "trying to open %s file descriptors\n", strbuff); 30713498266Sopenharmony_ci 30813498266Sopenharmony_ci /* open a dummy descriptor */ 30913498266Sopenharmony_ci 31013498266Sopenharmony_ci fd[0] = open(DEV_NULL, O_RDONLY); 31113498266Sopenharmony_ci if(fd[0] < 0) { 31213498266Sopenharmony_ci msnprintf(strbuff, sizeof(strbuff), "opening of %s failed", DEV_NULL); 31313498266Sopenharmony_ci store_errmsg(strbuff, errno); 31413498266Sopenharmony_ci fprintf(stderr, "%s\n", msgbuff); 31513498266Sopenharmony_ci free(fd); 31613498266Sopenharmony_ci fd = NULL; 31713498266Sopenharmony_ci free(memchunk); 31813498266Sopenharmony_ci return -7; 31913498266Sopenharmony_ci } 32013498266Sopenharmony_ci 32113498266Sopenharmony_ci /* create a bunch of file descriptors */ 32213498266Sopenharmony_ci 32313498266Sopenharmony_ci for(num_open.rlim_cur = 1; 32413498266Sopenharmony_ci num_open.rlim_cur < num_open.rlim_max; 32513498266Sopenharmony_ci num_open.rlim_cur++) { 32613498266Sopenharmony_ci 32713498266Sopenharmony_ci fd[num_open.rlim_cur] = dup(fd[0]); 32813498266Sopenharmony_ci 32913498266Sopenharmony_ci if(fd[num_open.rlim_cur] < 0) { 33013498266Sopenharmony_ci 33113498266Sopenharmony_ci fd[num_open.rlim_cur] = -1; 33213498266Sopenharmony_ci 33313498266Sopenharmony_ci rlim2str(strbuff1, sizeof(strbuff1), num_open.rlim_cur); 33413498266Sopenharmony_ci msnprintf(strbuff, sizeof(strbuff), "dup() attempt %s failed", strbuff1); 33513498266Sopenharmony_ci fprintf(stderr, "%s\n", strbuff); 33613498266Sopenharmony_ci 33713498266Sopenharmony_ci rlim2str(strbuff1, sizeof(strbuff1), num_open.rlim_cur); 33813498266Sopenharmony_ci msnprintf(strbuff, sizeof(strbuff), "fds system limit seems close to %s", 33913498266Sopenharmony_ci strbuff1); 34013498266Sopenharmony_ci fprintf(stderr, "%s\n", strbuff); 34113498266Sopenharmony_ci 34213498266Sopenharmony_ci num_open.rlim_max = num_open.rlim_cur - SAFETY_MARGIN; 34313498266Sopenharmony_ci 34413498266Sopenharmony_ci num_open.rlim_cur -= num_open.rlim_max; 34513498266Sopenharmony_ci rlim2str(strbuff1, sizeof(strbuff1), num_open.rlim_cur); 34613498266Sopenharmony_ci msnprintf(strbuff, sizeof(strbuff), "closing %s file descriptors", 34713498266Sopenharmony_ci strbuff1); 34813498266Sopenharmony_ci fprintf(stderr, "%s\n", strbuff); 34913498266Sopenharmony_ci 35013498266Sopenharmony_ci for(num_open.rlim_cur = num_open.rlim_max; 35113498266Sopenharmony_ci fd[num_open.rlim_cur] >= 0; 35213498266Sopenharmony_ci num_open.rlim_cur++) { 35313498266Sopenharmony_ci close(fd[num_open.rlim_cur]); 35413498266Sopenharmony_ci fd[num_open.rlim_cur] = -1; 35513498266Sopenharmony_ci } 35613498266Sopenharmony_ci 35713498266Sopenharmony_ci rlim2str(strbuff, sizeof(strbuff), num_open.rlim_max); 35813498266Sopenharmony_ci fprintf(stderr, "shrinking array for %s file descriptors\n", strbuff); 35913498266Sopenharmony_ci 36013498266Sopenharmony_ci /* we don't care if we can't shrink it */ 36113498266Sopenharmony_ci 36213498266Sopenharmony_ci tmpfd = realloc(fd, sizeof(*fd) * (size_t)(num_open.rlim_max)); 36313498266Sopenharmony_ci if(tmpfd) { 36413498266Sopenharmony_ci fd = tmpfd; 36513498266Sopenharmony_ci tmpfd = NULL; 36613498266Sopenharmony_ci } 36713498266Sopenharmony_ci 36813498266Sopenharmony_ci break; 36913498266Sopenharmony_ci } 37013498266Sopenharmony_ci } 37113498266Sopenharmony_ci 37213498266Sopenharmony_ci rlim2str(strbuff, sizeof(strbuff), num_open.rlim_max); 37313498266Sopenharmony_ci fprintf(stderr, "%s file descriptors open\n", strbuff); 37413498266Sopenharmony_ci 37513498266Sopenharmony_ci#if !defined(HAVE_POLL_FINE) && !defined(USE_WINSOCK) 37613498266Sopenharmony_ci 37713498266Sopenharmony_ci /* 37813498266Sopenharmony_ci * when using select() instead of poll() we cannot test 37913498266Sopenharmony_ci * libcurl functionality with a socket number equal or 38013498266Sopenharmony_ci * greater than FD_SETSIZE. In any case, macro VERIFY_SOCK 38113498266Sopenharmony_ci * in lib/select.c enforces this check and protects libcurl 38213498266Sopenharmony_ci * from a possible crash. The effect of this protection 38313498266Sopenharmony_ci * is that test 537 will always fail, since the actual 38413498266Sopenharmony_ci * call to select() never takes place. We skip test 537 38513498266Sopenharmony_ci * with an indication that select limit would be exceeded. 38613498266Sopenharmony_ci */ 38713498266Sopenharmony_ci 38813498266Sopenharmony_ci num_open.rlim_cur = FD_SETSIZE - SAFETY_MARGIN; 38913498266Sopenharmony_ci if(num_open.rlim_max > num_open.rlim_cur) { 39013498266Sopenharmony_ci msnprintf(strbuff, sizeof(strbuff), "select limit is FD_SETSIZE %d", 39113498266Sopenharmony_ci FD_SETSIZE); 39213498266Sopenharmony_ci store_errmsg(strbuff, 0); 39313498266Sopenharmony_ci fprintf(stderr, "%s\n", msgbuff); 39413498266Sopenharmony_ci close_file_descriptors(); 39513498266Sopenharmony_ci free(memchunk); 39613498266Sopenharmony_ci return -8; 39713498266Sopenharmony_ci } 39813498266Sopenharmony_ci 39913498266Sopenharmony_ci num_open.rlim_cur = FD_SETSIZE - SAFETY_MARGIN; 40013498266Sopenharmony_ci for(rl.rlim_cur = 0; 40113498266Sopenharmony_ci rl.rlim_cur < num_open.rlim_max; 40213498266Sopenharmony_ci rl.rlim_cur++) { 40313498266Sopenharmony_ci if((fd[rl.rlim_cur] > 0) && 40413498266Sopenharmony_ci ((unsigned int)fd[rl.rlim_cur] > num_open.rlim_cur)) { 40513498266Sopenharmony_ci msnprintf(strbuff, sizeof(strbuff), "select limit is FD_SETSIZE %d", 40613498266Sopenharmony_ci FD_SETSIZE); 40713498266Sopenharmony_ci store_errmsg(strbuff, 0); 40813498266Sopenharmony_ci fprintf(stderr, "%s\n", msgbuff); 40913498266Sopenharmony_ci close_file_descriptors(); 41013498266Sopenharmony_ci free(memchunk); 41113498266Sopenharmony_ci return -9; 41213498266Sopenharmony_ci } 41313498266Sopenharmony_ci } 41413498266Sopenharmony_ci 41513498266Sopenharmony_ci#endif /* using a FD_SETSIZE bound select() */ 41613498266Sopenharmony_ci 41713498266Sopenharmony_ci /* 41813498266Sopenharmony_ci * Old or 'backwards compatible' implementations of stdio do not allow 41913498266Sopenharmony_ci * handling of streams with an underlying file descriptor number greater 42013498266Sopenharmony_ci * than 255, even when allowing high numbered file descriptors for sockets. 42113498266Sopenharmony_ci * At this point we have a big number of file descriptors which have been 42213498266Sopenharmony_ci * opened using dup(), so lets test the stdio implementation and discover 42313498266Sopenharmony_ci * if it is capable of fopen()ing some additional files. 42413498266Sopenharmony_ci */ 42513498266Sopenharmony_ci 42613498266Sopenharmony_ci if(!fopen_works()) { 42713498266Sopenharmony_ci rlim2str(strbuff1, sizeof(strbuff1), num_open.rlim_max); 42813498266Sopenharmony_ci msnprintf(strbuff, sizeof(strbuff), "fopen fails with %s fds open", 42913498266Sopenharmony_ci strbuff1); 43013498266Sopenharmony_ci fprintf(stderr, "%s\n", msgbuff); 43113498266Sopenharmony_ci msnprintf(strbuff, sizeof(strbuff), "fopen fails with lots of fds open"); 43213498266Sopenharmony_ci store_errmsg(strbuff, 0); 43313498266Sopenharmony_ci close_file_descriptors(); 43413498266Sopenharmony_ci free(memchunk); 43513498266Sopenharmony_ci return -10; 43613498266Sopenharmony_ci } 43713498266Sopenharmony_ci 43813498266Sopenharmony_ci /* free the chunk of memory we were reserving so that it 43913498266Sopenharmony_ci becomes becomes available to the test */ 44013498266Sopenharmony_ci 44113498266Sopenharmony_ci free(memchunk); 44213498266Sopenharmony_ci 44313498266Sopenharmony_ci /* close file descriptors unless instructed to keep them */ 44413498266Sopenharmony_ci 44513498266Sopenharmony_ci if(!keep_open) { 44613498266Sopenharmony_ci close_file_descriptors(); 44713498266Sopenharmony_ci } 44813498266Sopenharmony_ci 44913498266Sopenharmony_ci return 0; 45013498266Sopenharmony_ci} 45113498266Sopenharmony_ci 45213498266Sopenharmony_ciint test(char *URL) 45313498266Sopenharmony_ci{ 45413498266Sopenharmony_ci CURLcode res; 45513498266Sopenharmony_ci CURL *curl; 45613498266Sopenharmony_ci 45713498266Sopenharmony_ci if(!strcmp(URL, "check")) { 45813498266Sopenharmony_ci /* used by the test script to ask if we can run this test or not */ 45913498266Sopenharmony_ci if(rlimit(FALSE)) { 46013498266Sopenharmony_ci fprintf(stdout, "rlimit problem: %s\n", msgbuff); 46113498266Sopenharmony_ci return 1; 46213498266Sopenharmony_ci } 46313498266Sopenharmony_ci return 0; /* sure, run this! */ 46413498266Sopenharmony_ci } 46513498266Sopenharmony_ci 46613498266Sopenharmony_ci if(rlimit(TRUE)) { 46713498266Sopenharmony_ci /* failure */ 46813498266Sopenharmony_ci return TEST_ERR_MAJOR_BAD; 46913498266Sopenharmony_ci } 47013498266Sopenharmony_ci 47113498266Sopenharmony_ci /* run the test with the bunch of open file descriptors 47213498266Sopenharmony_ci and close them all once the test is over */ 47313498266Sopenharmony_ci 47413498266Sopenharmony_ci if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { 47513498266Sopenharmony_ci fprintf(stderr, "curl_global_init() failed\n"); 47613498266Sopenharmony_ci close_file_descriptors(); 47713498266Sopenharmony_ci return TEST_ERR_MAJOR_BAD; 47813498266Sopenharmony_ci } 47913498266Sopenharmony_ci 48013498266Sopenharmony_ci curl = curl_easy_init(); 48113498266Sopenharmony_ci if(!curl) { 48213498266Sopenharmony_ci fprintf(stderr, "curl_easy_init() failed\n"); 48313498266Sopenharmony_ci close_file_descriptors(); 48413498266Sopenharmony_ci curl_global_cleanup(); 48513498266Sopenharmony_ci return TEST_ERR_MAJOR_BAD; 48613498266Sopenharmony_ci } 48713498266Sopenharmony_ci 48813498266Sopenharmony_ci test_setopt(curl, CURLOPT_URL, URL); 48913498266Sopenharmony_ci test_setopt(curl, CURLOPT_HEADER, 1L); 49013498266Sopenharmony_ci 49113498266Sopenharmony_ci res = curl_easy_perform(curl); 49213498266Sopenharmony_ci 49313498266Sopenharmony_citest_cleanup: 49413498266Sopenharmony_ci 49513498266Sopenharmony_ci close_file_descriptors(); 49613498266Sopenharmony_ci curl_easy_cleanup(curl); 49713498266Sopenharmony_ci curl_global_cleanup(); 49813498266Sopenharmony_ci 49913498266Sopenharmony_ci return (int)res; 50013498266Sopenharmony_ci} 50113498266Sopenharmony_ci 50213498266Sopenharmony_ci#else /* defined(HAVE_GETRLIMIT) && defined(HAVE_SETRLIMIT) */ 50313498266Sopenharmony_ci 50413498266Sopenharmony_ciint test(char *URL) 50513498266Sopenharmony_ci{ 50613498266Sopenharmony_ci (void)URL; 50713498266Sopenharmony_ci printf("system lacks necessary system function(s)"); 50813498266Sopenharmony_ci return 1; /* skip test */ 50913498266Sopenharmony_ci} 51013498266Sopenharmony_ci 51113498266Sopenharmony_ci#endif /* defined(HAVE_GETRLIMIT) && defined(HAVE_SETRLIMIT) */ 512