mirror of
https://github.com/shadowsocks/shadowsocks-libev.git
synced 2026-10-18 03:26:48 +00:00
Raise the file descriptor limit for descriptor-heavy tests
test_event opens 256 UDP receivers plus a sender on top of the loop's own descriptors. macOS starts processes with a soft RLIMIT_NOFILE of 256, so socket() eventually returned -1 and the unchecked descriptor tripped the bind() assertion when running ctest from a stock terminal (#3058). Wrap every registered unit test in a small sh launcher that raises the soft limit to 1024 before exec'ing the binary, and have test_event raise its own limit as well so it also passes when run directly. Assert on socket() failures so a limit problem is reported as such instead of as a bind error. Fixes #3058 Claude-Session: https://claude.ai/code/session_01PSG4XV3jiqitDgdgFSGATx
This commit is contained in:
+10
-2
@@ -10,6 +10,14 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
find_program(VALGRIND_EXECUTABLE NAMES valgrind)
|
||||
endif()
|
||||
|
||||
# Some hosts (notably macOS, whose default soft limit is 256) start test
|
||||
# processes with too few file descriptors for descriptor-heavy tests such as
|
||||
# test_event. Raise the soft limit before exec'ing each test; a failure to
|
||||
# raise it (hard limit too low) is ignored so the test still runs.
|
||||
if(NOT WIN32)
|
||||
set(SS_TEST_LAUNCHER sh -c "ulimit -n 1024 2>/dev/null\; exec \"$0\" \"$@\"")
|
||||
endif()
|
||||
|
||||
# Helper function to add a unit test
|
||||
function(ss_add_test name sources libs)
|
||||
if(WIN32 AND "${sources}" MATCHES "utils.c")
|
||||
@@ -28,12 +36,12 @@ function(ss_add_test name sources libs)
|
||||
else()
|
||||
target_compile_options(${name} PRIVATE -UNDEBUG)
|
||||
endif()
|
||||
add_test(NAME ${name} COMMAND ${name})
|
||||
add_test(NAME ${name} COMMAND ${SS_TEST_LAUNCHER} $<TARGET_FILE:${name}>)
|
||||
set_tests_properties(${name} PROPERTIES LABELS "unit")
|
||||
|
||||
if(VALGRIND_EXECUTABLE)
|
||||
add_test(NAME memcheck_${name}
|
||||
COMMAND ${VALGRIND_EXECUTABLE}
|
||||
COMMAND ${SS_TEST_LAUNCHER} ${VALGRIND_EXECUTABLE}
|
||||
--tool=memcheck
|
||||
--leak-check=full
|
||||
--show-leak-kinds=definite,indirect
|
||||
|
||||
@@ -35,6 +35,8 @@ static void must_not_run(struct ss_loop *loop, ss_io *io, int events)
|
||||
int main(void)
|
||||
{
|
||||
test_network_init();
|
||||
/* 256 receivers + sender + loop internals must fit under RLIMIT_NOFILE. */
|
||||
test_raise_fd_limit(512);
|
||||
struct ss_loop *loop = ss_loop_new(0);
|
||||
assert(loop);
|
||||
#ifdef _WIN32
|
||||
@@ -48,8 +50,10 @@ int main(void)
|
||||
/* Exceed Winsock select's default 64 descriptors. */
|
||||
struct receiver receivers[256] = {0};
|
||||
ss_socket_t sender = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
assert((int)sender >= 0);
|
||||
for (unsigned i = 0; i < 256; i++) {
|
||||
int fd = (int)socket(AF_INET, SOCK_DGRAM, 0);
|
||||
assert(fd >= 0);
|
||||
struct sockaddr_in address = {0};
|
||||
address.sin_family = AF_INET;
|
||||
address.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "platform.h"
|
||||
#ifndef _WIN32
|
||||
#include <sys/resource.h>
|
||||
#endif
|
||||
|
||||
static inline void test_network_cleanup(void)
|
||||
{
|
||||
@@ -19,6 +22,25 @@ static inline void test_network_init(void)
|
||||
assert(atexit(test_network_cleanup) == 0);
|
||||
#endif
|
||||
}
|
||||
/* Make sure at least `want` descriptors can be opened; the default soft
|
||||
* limit is only 256 on macOS, which is below what descriptor-heavy tests
|
||||
* such as test_event need. Windows sockets are not bounded by RLIMIT_NOFILE. */
|
||||
static inline void test_raise_fd_limit(unsigned want)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
struct rlimit limit;
|
||||
assert(getrlimit(RLIMIT_NOFILE, &limit) == 0);
|
||||
if (limit.rlim_cur != RLIM_INFINITY && limit.rlim_cur < want) {
|
||||
limit.rlim_cur = want;
|
||||
if (limit.rlim_max != RLIM_INFINITY && limit.rlim_max < limit.rlim_cur) {
|
||||
limit.rlim_cur = limit.rlim_max;
|
||||
}
|
||||
assert(setrlimit(RLIMIT_NOFILE, &limit) == 0);
|
||||
}
|
||||
#else
|
||||
(void)want;
|
||||
#endif
|
||||
}
|
||||
static inline FILE *test_tempfile(char *path, size_t size)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
||||
Reference in New Issue
Block a user