|
|
|
@ -5,6 +5,7 @@ |
|
|
|
#include <fcntl.h> |
|
|
|
#include <fcntl.h> |
|
|
|
#include <pthread.h> |
|
|
|
#include <pthread.h> |
|
|
|
#include <string.h> |
|
|
|
#include <string.h> |
|
|
|
|
|
|
|
#include <sys/resource.h> |
|
|
|
#include <sys/socket.h> |
|
|
|
#include <sys/socket.h> |
|
|
|
#include <unistd.h> |
|
|
|
#include <unistd.h> |
|
|
|
|
|
|
|
|
|
|
|
@ -102,10 +103,41 @@ static int test_fd_mapping(int param) { |
|
|
|
socket_cleanup(&t); return 0; |
|
|
|
socket_cleanup(&t); return 0; |
|
|
|
} |
|
|
|
} |
|
|
|
static int test_lookup(int param) { |
|
|
|
static int test_lookup(int param) { |
|
|
|
|
|
|
|
const int min_fd = FD_SETSIZE + 16; |
|
|
|
|
|
|
|
if (param & 4) { |
|
|
|
|
|
|
|
struct rlimit limit; |
|
|
|
|
|
|
|
if (getrlimit(RLIMIT_NOFILE, &limit) != 0) { |
|
|
|
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_SYS, "getrlimit(RLIMIT_NOFILE): %s", strerror(errno)); |
|
|
|
|
|
|
|
return 1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
DEBUG_DEBUG(DEBUG_CATEGORY_SYS, "High-fd test: min_fd=%d, soft=%llu, hard=%llu", min_fd, |
|
|
|
|
|
|
|
(unsigned long long)limit.rlim_cur, (unsigned long long)limit.rlim_max); |
|
|
|
|
|
|
|
if (limit.rlim_max <= (rlim_t)min_fd) { |
|
|
|
|
|
|
|
DEBUG_WARN(DEBUG_CATEGORY_SYS, "Skipping high-fd test: fd >= %d requires RLIMIT_NOFILE > %d, hard=%llu", |
|
|
|
|
|
|
|
min_fd, min_fd, (unsigned long long)limit.rlim_max); |
|
|
|
|
|
|
|
return 77; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// Каждый случай работает в дочернем процессе; лимит родителя не меняется.
|
|
|
|
|
|
|
|
if (limit.rlim_cur <= (rlim_t)min_fd) { |
|
|
|
|
|
|
|
limit.rlim_cur = (rlim_t)min_fd + 1; |
|
|
|
|
|
|
|
if (setrlimit(RLIMIT_NOFILE, &limit) != 0) { |
|
|
|
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_SYS, "setrlimit(RLIMIT_NOFILE, %llu): %s", |
|
|
|
|
|
|
|
(unsigned long long)limit.rlim_cur, strerror(errno)); |
|
|
|
|
|
|
|
return 1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
DEBUG_DEBUG(DEBUG_CATEGORY_SYS, "High-fd test: raised soft limit to %llu", (unsigned long long)limit.rlim_cur); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
struct socket_test t; CHECK_EQ(socket_setup(&t, param & 3, 1, 0, 0), 0); |
|
|
|
struct socket_test t; CHECK_EQ(socket_setup(&t, param & 3, 1, 0, 0), 0); |
|
|
|
if (param & 4) { |
|
|
|
if (param & 4) { |
|
|
|
CHECK_EQ(uasync_remove_socket(t.ua, t.id), ERR_OK); t.id = NULL; |
|
|
|
CHECK_EQ(uasync_remove_socket(t.ua, t.id), ERR_OK); t.id = NULL; |
|
|
|
int high = fcntl(t.fd[0], F_DUPFD, FD_SETSIZE + 16); CHECK(high >= FD_SETSIZE); |
|
|
|
int high = fcntl(t.fd[0], F_DUPFD, min_fd); |
|
|
|
|
|
|
|
if (high < 0) { |
|
|
|
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_SYS, "fcntl(fd=%d, F_DUPFD, min_fd=%d): %s", t.fd[0], min_fd, strerror(errno)); |
|
|
|
|
|
|
|
socket_cleanup(&t); return 1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
CHECK(high >= min_fd); |
|
|
|
|
|
|
|
DEBUG_DEBUG(DEBUG_CATEGORY_SYS, "High-fd test: allocated fd=%d", high); |
|
|
|
close(t.fd[0]); t.fd[0] = high; |
|
|
|
close(t.fd[0]); t.fd[0] = high; |
|
|
|
t.id = uasync_add_socket(t.ua, high, read_cb, NULL, NULL, "high fd", &t); CHECK(t.id); |
|
|
|
t.id = uasync_add_socket(t.ua, high, read_cb, NULL, NULL, "high fd", &t); CHECK(t.id); |
|
|
|
} |
|
|
|
} |
|
|
|
|