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#ifndef FD_SETSIZE 3813498266Sopenharmony_ci#error "this test requires FD_SETSIZE" 3913498266Sopenharmony_ci#endif 4013498266Sopenharmony_ci 4113498266Sopenharmony_ci#define SAFETY_MARGIN (16) 4213498266Sopenharmony_ci#define NUM_OPEN (FD_SETSIZE + 10) 4313498266Sopenharmony_ci#define NUM_NEEDED (NUM_OPEN + SAFETY_MARGIN) 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 rlim_t nitems, i; 12613498266Sopenharmony_ci int *memchunk = NULL; 12713498266Sopenharmony_ci struct rlimit rl; 12813498266Sopenharmony_ci char strbuff[256]; 12913498266Sopenharmony_ci char strbuff1[81]; 13013498266Sopenharmony_ci char strbuff2[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 /* show our constants */ 14913498266Sopenharmony_ci 15013498266Sopenharmony_ci fprintf(stderr, "test518 FD_SETSIZE: %d\n", FD_SETSIZE); 15113498266Sopenharmony_ci fprintf(stderr, "test518 NUM_OPEN : %d\n", NUM_OPEN); 15213498266Sopenharmony_ci fprintf(stderr, "test518 NUM_NEEDED: %d\n", NUM_NEEDED); 15313498266Sopenharmony_ci 15413498266Sopenharmony_ci /* 15513498266Sopenharmony_ci * if soft limit and hard limit are different we ask the 15613498266Sopenharmony_ci * system to raise soft limit all the way up to the hard 15713498266Sopenharmony_ci * limit. Due to some other system limit the soft limit 15813498266Sopenharmony_ci * might not be raised up to the hard limit. So from this 15913498266Sopenharmony_ci * point the resulting soft limit is our limit. Trying to 16013498266Sopenharmony_ci * open more than soft limit file descriptors will fail. 16113498266Sopenharmony_ci */ 16213498266Sopenharmony_ci 16313498266Sopenharmony_ci if(rl.rlim_cur != rl.rlim_max) { 16413498266Sopenharmony_ci 16513498266Sopenharmony_ci#ifdef OPEN_MAX 16613498266Sopenharmony_ci if((rl.rlim_cur > 0) && 16713498266Sopenharmony_ci (rl.rlim_cur < OPEN_MAX)) { 16813498266Sopenharmony_ci fprintf(stderr, "raising soft limit up to OPEN_MAX\n"); 16913498266Sopenharmony_ci rl.rlim_cur = OPEN_MAX; 17013498266Sopenharmony_ci if(setrlimit(RLIMIT_NOFILE, &rl) != 0) { 17113498266Sopenharmony_ci /* on failure don't abort just issue a warning */ 17213498266Sopenharmony_ci store_errmsg("setrlimit() failed", errno); 17313498266Sopenharmony_ci fprintf(stderr, "%s\n", msgbuff); 17413498266Sopenharmony_ci msgbuff[0] = '\0'; 17513498266Sopenharmony_ci } 17613498266Sopenharmony_ci } 17713498266Sopenharmony_ci#endif 17813498266Sopenharmony_ci 17913498266Sopenharmony_ci fprintf(stderr, "raising soft limit up to hard limit\n"); 18013498266Sopenharmony_ci rl.rlim_cur = rl.rlim_max; 18113498266Sopenharmony_ci if(setrlimit(RLIMIT_NOFILE, &rl) != 0) { 18213498266Sopenharmony_ci /* on failure don't abort just issue a warning */ 18313498266Sopenharmony_ci store_errmsg("setrlimit() failed", errno); 18413498266Sopenharmony_ci fprintf(stderr, "%s\n", msgbuff); 18513498266Sopenharmony_ci msgbuff[0] = '\0'; 18613498266Sopenharmony_ci } 18713498266Sopenharmony_ci 18813498266Sopenharmony_ci /* get current open file limits */ 18913498266Sopenharmony_ci 19013498266Sopenharmony_ci if(getrlimit(RLIMIT_NOFILE, &rl) != 0) { 19113498266Sopenharmony_ci store_errmsg("getrlimit() failed", errno); 19213498266Sopenharmony_ci fprintf(stderr, "%s\n", msgbuff); 19313498266Sopenharmony_ci return -3; 19413498266Sopenharmony_ci } 19513498266Sopenharmony_ci 19613498266Sopenharmony_ci /* show current open file limits */ 19713498266Sopenharmony_ci 19813498266Sopenharmony_ci rlim2str(strbuff, sizeof(strbuff), rl.rlim_cur); 19913498266Sopenharmony_ci fprintf(stderr, "current soft limit: %s\n", strbuff); 20013498266Sopenharmony_ci 20113498266Sopenharmony_ci rlim2str(strbuff, sizeof(strbuff), rl.rlim_max); 20213498266Sopenharmony_ci fprintf(stderr, "current hard limit: %s\n", strbuff); 20313498266Sopenharmony_ci 20413498266Sopenharmony_ci } /* (rl.rlim_cur != rl.rlim_max) */ 20513498266Sopenharmony_ci 20613498266Sopenharmony_ci /* 20713498266Sopenharmony_ci * test 518 is all about testing libcurl functionality 20813498266Sopenharmony_ci * when more than FD_SETSIZE file descriptors are open. 20913498266Sopenharmony_ci * This means that if for any reason we are not able to 21013498266Sopenharmony_ci * open more than FD_SETSIZE file descriptors then test 21113498266Sopenharmony_ci * 518 should not be run. 21213498266Sopenharmony_ci */ 21313498266Sopenharmony_ci 21413498266Sopenharmony_ci /* 21513498266Sopenharmony_ci * verify that soft limit is higher than NUM_NEEDED, 21613498266Sopenharmony_ci * which is the number of file descriptors we would 21713498266Sopenharmony_ci * try to open plus SAFETY_MARGIN to not exhaust the 21813498266Sopenharmony_ci * file descriptor pool 21913498266Sopenharmony_ci */ 22013498266Sopenharmony_ci 22113498266Sopenharmony_ci num_open.rlim_cur = NUM_NEEDED; 22213498266Sopenharmony_ci 22313498266Sopenharmony_ci if((rl.rlim_cur > 0) && 22413498266Sopenharmony_ci#ifdef RLIM_INFINITY 22513498266Sopenharmony_ci (rl.rlim_cur != RLIM_INFINITY) && 22613498266Sopenharmony_ci#endif 22713498266Sopenharmony_ci (rl.rlim_cur <= num_open.rlim_cur)) { 22813498266Sopenharmony_ci rlim2str(strbuff2, sizeof(strbuff2), rl.rlim_cur); 22913498266Sopenharmony_ci rlim2str(strbuff1, sizeof(strbuff1), num_open.rlim_cur); 23013498266Sopenharmony_ci msnprintf(strbuff, sizeof(strbuff), "fds needed %s > system limit %s", 23113498266Sopenharmony_ci strbuff1, strbuff2); 23213498266Sopenharmony_ci store_errmsg(strbuff, 0); 23313498266Sopenharmony_ci fprintf(stderr, "%s\n", msgbuff); 23413498266Sopenharmony_ci return -4; 23513498266Sopenharmony_ci } 23613498266Sopenharmony_ci 23713498266Sopenharmony_ci /* 23813498266Sopenharmony_ci * reserve a chunk of memory before opening file descriptors to 23913498266Sopenharmony_ci * avoid a low memory condition once the file descriptors are 24013498266Sopenharmony_ci * open. System conditions that could make the test fail should 24113498266Sopenharmony_ci * be addressed in the precheck phase. This chunk of memory shall 24213498266Sopenharmony_ci * be always free()ed before exiting the rlimit() function so 24313498266Sopenharmony_ci * that it becomes available to the test. 24413498266Sopenharmony_ci */ 24513498266Sopenharmony_ci 24613498266Sopenharmony_ci for(nitems = i = 1; nitems <= i; i *= 2) 24713498266Sopenharmony_ci nitems = i; 24813498266Sopenharmony_ci if(nitems > 0x7fff) 24913498266Sopenharmony_ci nitems = 0x40000; 25013498266Sopenharmony_ci do { 25113498266Sopenharmony_ci num_open.rlim_max = sizeof(*memchunk) * nitems; 25213498266Sopenharmony_ci rlim2str(strbuff, sizeof(strbuff), num_open.rlim_max); 25313498266Sopenharmony_ci fprintf(stderr, "allocating memchunk %s byte array\n", strbuff); 25413498266Sopenharmony_ci memchunk = malloc(sizeof(*memchunk) * (size_t)nitems); 25513498266Sopenharmony_ci if(!memchunk) { 25613498266Sopenharmony_ci fprintf(stderr, "memchunk, malloc() failed\n"); 25713498266Sopenharmony_ci nitems /= 2; 25813498266Sopenharmony_ci } 25913498266Sopenharmony_ci } while(nitems && !memchunk); 26013498266Sopenharmony_ci if(!memchunk) { 26113498266Sopenharmony_ci store_errmsg("memchunk, malloc() failed", errno); 26213498266Sopenharmony_ci fprintf(stderr, "%s\n", msgbuff); 26313498266Sopenharmony_ci return -5; 26413498266Sopenharmony_ci } 26513498266Sopenharmony_ci 26613498266Sopenharmony_ci /* initialize it to fight lazy allocation */ 26713498266Sopenharmony_ci 26813498266Sopenharmony_ci fprintf(stderr, "initializing memchunk array\n"); 26913498266Sopenharmony_ci 27013498266Sopenharmony_ci for(i = 0; i < nitems; i++) 27113498266Sopenharmony_ci memchunk[i] = -1; 27213498266Sopenharmony_ci 27313498266Sopenharmony_ci /* set the number of file descriptors we will try to open */ 27413498266Sopenharmony_ci 27513498266Sopenharmony_ci num_open.rlim_max = NUM_OPEN; 27613498266Sopenharmony_ci 27713498266Sopenharmony_ci /* verify that we won't overflow size_t in malloc() */ 27813498266Sopenharmony_ci 27913498266Sopenharmony_ci if((size_t)(num_open.rlim_max) > ((size_t)-1) / sizeof(*fd)) { 28013498266Sopenharmony_ci rlim2str(strbuff1, sizeof(strbuff1), num_open.rlim_max); 28113498266Sopenharmony_ci msnprintf(strbuff, sizeof(strbuff), "unable to allocate an array for %s " 28213498266Sopenharmony_ci "file descriptors, would overflow size_t", strbuff1); 28313498266Sopenharmony_ci store_errmsg(strbuff, 0); 28413498266Sopenharmony_ci fprintf(stderr, "%s\n", msgbuff); 28513498266Sopenharmony_ci free(memchunk); 28613498266Sopenharmony_ci return -6; 28713498266Sopenharmony_ci } 28813498266Sopenharmony_ci 28913498266Sopenharmony_ci /* allocate array for file descriptors */ 29013498266Sopenharmony_ci 29113498266Sopenharmony_ci rlim2str(strbuff, sizeof(strbuff), num_open.rlim_max); 29213498266Sopenharmony_ci fprintf(stderr, "allocating array for %s file descriptors\n", strbuff); 29313498266Sopenharmony_ci 29413498266Sopenharmony_ci fd = malloc(sizeof(*fd) * (size_t)(num_open.rlim_max)); 29513498266Sopenharmony_ci if(!fd) { 29613498266Sopenharmony_ci store_errmsg("fd, malloc() failed", errno); 29713498266Sopenharmony_ci fprintf(stderr, "%s\n", msgbuff); 29813498266Sopenharmony_ci free(memchunk); 29913498266Sopenharmony_ci return -7; 30013498266Sopenharmony_ci } 30113498266Sopenharmony_ci 30213498266Sopenharmony_ci /* initialize it to fight lazy allocation */ 30313498266Sopenharmony_ci 30413498266Sopenharmony_ci fprintf(stderr, "initializing fd array\n"); 30513498266Sopenharmony_ci 30613498266Sopenharmony_ci for(num_open.rlim_cur = 0; 30713498266Sopenharmony_ci num_open.rlim_cur < num_open.rlim_max; 30813498266Sopenharmony_ci num_open.rlim_cur++) 30913498266Sopenharmony_ci fd[num_open.rlim_cur] = -1; 31013498266Sopenharmony_ci 31113498266Sopenharmony_ci rlim2str(strbuff, sizeof(strbuff), num_open.rlim_max); 31213498266Sopenharmony_ci fprintf(stderr, "trying to open %s file descriptors\n", strbuff); 31313498266Sopenharmony_ci 31413498266Sopenharmony_ci /* open a dummy descriptor */ 31513498266Sopenharmony_ci 31613498266Sopenharmony_ci fd[0] = open(DEV_NULL, O_RDONLY); 31713498266Sopenharmony_ci if(fd[0] < 0) { 31813498266Sopenharmony_ci msnprintf(strbuff, sizeof(strbuff), "opening of %s failed", DEV_NULL); 31913498266Sopenharmony_ci store_errmsg(strbuff, errno); 32013498266Sopenharmony_ci fprintf(stderr, "%s\n", msgbuff); 32113498266Sopenharmony_ci free(fd); 32213498266Sopenharmony_ci fd = NULL; 32313498266Sopenharmony_ci free(memchunk); 32413498266Sopenharmony_ci return -8; 32513498266Sopenharmony_ci } 32613498266Sopenharmony_ci 32713498266Sopenharmony_ci /* create a bunch of file descriptors */ 32813498266Sopenharmony_ci 32913498266Sopenharmony_ci for(num_open.rlim_cur = 1; 33013498266Sopenharmony_ci num_open.rlim_cur < num_open.rlim_max; 33113498266Sopenharmony_ci num_open.rlim_cur++) { 33213498266Sopenharmony_ci 33313498266Sopenharmony_ci fd[num_open.rlim_cur] = dup(fd[0]); 33413498266Sopenharmony_ci 33513498266Sopenharmony_ci if(fd[num_open.rlim_cur] < 0) { 33613498266Sopenharmony_ci 33713498266Sopenharmony_ci fd[num_open.rlim_cur] = -1; 33813498266Sopenharmony_ci 33913498266Sopenharmony_ci rlim2str(strbuff1, sizeof(strbuff1), num_open.rlim_cur); 34013498266Sopenharmony_ci msnprintf(strbuff, sizeof(strbuff), "dup() attempt %s failed", strbuff1); 34113498266Sopenharmony_ci fprintf(stderr, "%s\n", strbuff); 34213498266Sopenharmony_ci 34313498266Sopenharmony_ci rlim2str(strbuff1, sizeof(strbuff1), num_open.rlim_cur); 34413498266Sopenharmony_ci msnprintf(strbuff, sizeof(strbuff), "fds system limit seems close to %s", 34513498266Sopenharmony_ci strbuff1); 34613498266Sopenharmony_ci fprintf(stderr, "%s\n", strbuff); 34713498266Sopenharmony_ci 34813498266Sopenharmony_ci num_open.rlim_max = NUM_NEEDED; 34913498266Sopenharmony_ci 35013498266Sopenharmony_ci rlim2str(strbuff2, sizeof(strbuff2), num_open.rlim_max); 35113498266Sopenharmony_ci rlim2str(strbuff1, sizeof(strbuff1), num_open.rlim_cur); 35213498266Sopenharmony_ci msnprintf(strbuff, sizeof(strbuff), "fds needed %s > system limit %s", 35313498266Sopenharmony_ci strbuff2, strbuff1); 35413498266Sopenharmony_ci store_errmsg(strbuff, 0); 35513498266Sopenharmony_ci fprintf(stderr, "%s\n", msgbuff); 35613498266Sopenharmony_ci 35713498266Sopenharmony_ci for(num_open.rlim_cur = 0; 35813498266Sopenharmony_ci fd[num_open.rlim_cur] >= 0; 35913498266Sopenharmony_ci num_open.rlim_cur++) 36013498266Sopenharmony_ci close(fd[num_open.rlim_cur]); 36113498266Sopenharmony_ci free(fd); 36213498266Sopenharmony_ci fd = NULL; 36313498266Sopenharmony_ci free(memchunk); 36413498266Sopenharmony_ci return -9; 36513498266Sopenharmony_ci } 36613498266Sopenharmony_ci } 36713498266Sopenharmony_ci 36813498266Sopenharmony_ci rlim2str(strbuff, sizeof(strbuff), num_open.rlim_max); 36913498266Sopenharmony_ci fprintf(stderr, "%s file descriptors open\n", strbuff); 37013498266Sopenharmony_ci 37113498266Sopenharmony_ci#if !defined(HAVE_POLL_FINE) && !defined(USE_WINSOCK) 37213498266Sopenharmony_ci 37313498266Sopenharmony_ci /* 37413498266Sopenharmony_ci * when using select() instead of poll() we cannot test 37513498266Sopenharmony_ci * libcurl functionality with a socket number equal or 37613498266Sopenharmony_ci * greater than FD_SETSIZE. In any case, macro VERIFY_SOCK 37713498266Sopenharmony_ci * in lib/select.c enforces this check and protects libcurl 37813498266Sopenharmony_ci * from a possible crash. The effect of this protection 37913498266Sopenharmony_ci * is that test 518 will always fail, since the actual 38013498266Sopenharmony_ci * call to select() never takes place. We skip test 518 38113498266Sopenharmony_ci * with an indication that select limit would be exceeded. 38213498266Sopenharmony_ci */ 38313498266Sopenharmony_ci 38413498266Sopenharmony_ci num_open.rlim_cur = FD_SETSIZE - SAFETY_MARGIN; 38513498266Sopenharmony_ci if(num_open.rlim_max > num_open.rlim_cur) { 38613498266Sopenharmony_ci msnprintf(strbuff, sizeof(strbuff), "select limit is FD_SETSIZE %d", 38713498266Sopenharmony_ci FD_SETSIZE); 38813498266Sopenharmony_ci store_errmsg(strbuff, 0); 38913498266Sopenharmony_ci fprintf(stderr, "%s\n", msgbuff); 39013498266Sopenharmony_ci close_file_descriptors(); 39113498266Sopenharmony_ci free(memchunk); 39213498266Sopenharmony_ci return -10; 39313498266Sopenharmony_ci } 39413498266Sopenharmony_ci 39513498266Sopenharmony_ci num_open.rlim_cur = FD_SETSIZE - SAFETY_MARGIN; 39613498266Sopenharmony_ci for(rl.rlim_cur = 0; 39713498266Sopenharmony_ci rl.rlim_cur < num_open.rlim_max; 39813498266Sopenharmony_ci rl.rlim_cur++) { 39913498266Sopenharmony_ci if((fd[rl.rlim_cur] > 0) && 40013498266Sopenharmony_ci ((unsigned int)fd[rl.rlim_cur] > num_open.rlim_cur)) { 40113498266Sopenharmony_ci msnprintf(strbuff, sizeof(strbuff), "select limit is FD_SETSIZE %d", 40213498266Sopenharmony_ci FD_SETSIZE); 40313498266Sopenharmony_ci store_errmsg(strbuff, 0); 40413498266Sopenharmony_ci fprintf(stderr, "%s\n", msgbuff); 40513498266Sopenharmony_ci close_file_descriptors(); 40613498266Sopenharmony_ci free(memchunk); 40713498266Sopenharmony_ci return -11; 40813498266Sopenharmony_ci } 40913498266Sopenharmony_ci } 41013498266Sopenharmony_ci 41113498266Sopenharmony_ci#endif /* using a FD_SETSIZE bound select() */ 41213498266Sopenharmony_ci 41313498266Sopenharmony_ci /* 41413498266Sopenharmony_ci * Old or 'backwards compatible' implementations of stdio do not allow 41513498266Sopenharmony_ci * handling of streams with an underlying file descriptor number greater 41613498266Sopenharmony_ci * than 255, even when allowing high numbered file descriptors for sockets. 41713498266Sopenharmony_ci * At this point we have a big number of file descriptors which have been 41813498266Sopenharmony_ci * opened using dup(), so lets test the stdio implementation and discover 41913498266Sopenharmony_ci * if it is capable of fopen()ing some additional files. 42013498266Sopenharmony_ci */ 42113498266Sopenharmony_ci 42213498266Sopenharmony_ci if(!fopen_works()) { 42313498266Sopenharmony_ci rlim2str(strbuff1, sizeof(strbuff1), num_open.rlim_max); 42413498266Sopenharmony_ci msnprintf(strbuff, sizeof(strbuff), "fopen fails with %s fds open", 42513498266Sopenharmony_ci strbuff1); 42613498266Sopenharmony_ci fprintf(stderr, "%s\n", msgbuff); 42713498266Sopenharmony_ci msnprintf(strbuff, sizeof(strbuff), "fopen fails with lots of fds open"); 42813498266Sopenharmony_ci store_errmsg(strbuff, 0); 42913498266Sopenharmony_ci close_file_descriptors(); 43013498266Sopenharmony_ci free(memchunk); 43113498266Sopenharmony_ci return -12; 43213498266Sopenharmony_ci } 43313498266Sopenharmony_ci 43413498266Sopenharmony_ci /* free the chunk of memory we were reserving so that it 43513498266Sopenharmony_ci becomes becomes available to the test */ 43613498266Sopenharmony_ci 43713498266Sopenharmony_ci free(memchunk); 43813498266Sopenharmony_ci 43913498266Sopenharmony_ci /* close file descriptors unless instructed to keep them */ 44013498266Sopenharmony_ci 44113498266Sopenharmony_ci if(!keep_open) { 44213498266Sopenharmony_ci close_file_descriptors(); 44313498266Sopenharmony_ci } 44413498266Sopenharmony_ci 44513498266Sopenharmony_ci return 0; 44613498266Sopenharmony_ci} 44713498266Sopenharmony_ci 44813498266Sopenharmony_ciint test(char *URL) 44913498266Sopenharmony_ci{ 45013498266Sopenharmony_ci CURLcode res; 45113498266Sopenharmony_ci CURL *curl; 45213498266Sopenharmony_ci 45313498266Sopenharmony_ci if(!strcmp(URL, "check")) { 45413498266Sopenharmony_ci /* used by the test script to ask if we can run this test or not */ 45513498266Sopenharmony_ci if(rlimit(FALSE)) { 45613498266Sopenharmony_ci fprintf(stdout, "rlimit problem: %s\n", msgbuff); 45713498266Sopenharmony_ci return 1; 45813498266Sopenharmony_ci } 45913498266Sopenharmony_ci return 0; /* sure, run this! */ 46013498266Sopenharmony_ci } 46113498266Sopenharmony_ci 46213498266Sopenharmony_ci if(rlimit(TRUE)) { 46313498266Sopenharmony_ci /* failure */ 46413498266Sopenharmony_ci return TEST_ERR_MAJOR_BAD; 46513498266Sopenharmony_ci } 46613498266Sopenharmony_ci 46713498266Sopenharmony_ci /* run the test with the bunch of open file descriptors 46813498266Sopenharmony_ci and close them all once the test is over */ 46913498266Sopenharmony_ci 47013498266Sopenharmony_ci if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { 47113498266Sopenharmony_ci fprintf(stderr, "curl_global_init() failed\n"); 47213498266Sopenharmony_ci close_file_descriptors(); 47313498266Sopenharmony_ci return TEST_ERR_MAJOR_BAD; 47413498266Sopenharmony_ci } 47513498266Sopenharmony_ci 47613498266Sopenharmony_ci curl = curl_easy_init(); 47713498266Sopenharmony_ci if(!curl) { 47813498266Sopenharmony_ci fprintf(stderr, "curl_easy_init() failed\n"); 47913498266Sopenharmony_ci close_file_descriptors(); 48013498266Sopenharmony_ci curl_global_cleanup(); 48113498266Sopenharmony_ci return TEST_ERR_MAJOR_BAD; 48213498266Sopenharmony_ci } 48313498266Sopenharmony_ci 48413498266Sopenharmony_ci test_setopt(curl, CURLOPT_URL, URL); 48513498266Sopenharmony_ci test_setopt(curl, CURLOPT_HEADER, 1L); 48613498266Sopenharmony_ci 48713498266Sopenharmony_ci res = curl_easy_perform(curl); 48813498266Sopenharmony_ci 48913498266Sopenharmony_citest_cleanup: 49013498266Sopenharmony_ci 49113498266Sopenharmony_ci close_file_descriptors(); 49213498266Sopenharmony_ci curl_easy_cleanup(curl); 49313498266Sopenharmony_ci curl_global_cleanup(); 49413498266Sopenharmony_ci 49513498266Sopenharmony_ci return (int)res; 49613498266Sopenharmony_ci} 49713498266Sopenharmony_ci 49813498266Sopenharmony_ci#else /* defined(HAVE_GETRLIMIT) && defined(HAVE_SETRLIMIT) */ 49913498266Sopenharmony_ci 50013498266Sopenharmony_ciint test(char *URL) 50113498266Sopenharmony_ci{ 50213498266Sopenharmony_ci (void)URL; 50313498266Sopenharmony_ci printf("system lacks necessary system function(s)"); 50413498266Sopenharmony_ci return 1; /* skip test */ 50513498266Sopenharmony_ci} 50613498266Sopenharmony_ci 50713498266Sopenharmony_ci#endif /* defined(HAVE_GETRLIMIT) && defined(HAVE_SETRLIMIT) */ 508