diff options
author | ngie <ngie@FreeBSD.org> | 2015-04-10 09:21:07 +0000 |
---|---|---|
committer | ngie <ngie@FreeBSD.org> | 2015-04-10 09:21:07 +0000 |
commit | eff63aa71f5016688ee0e95a091ca14a9316eb54 (patch) | |
tree | ccbfa404862393ebab8820fdac95a722b2a60450 /tools | |
parent | 469a6f6d983bccffa88972ecfd65fe30500b772c (diff) | |
download | FreeBSD-src-eff63aa71f5016688ee0e95a091ca14a9316eb54.zip FreeBSD-src-eff63aa71f5016688ee0e95a091ca14a9316eb54.tar.gz |
- Parameterize out the number of accept/connect attempts
- Randomize the bind port to allow 2+ consecutive calls in < 10 minutes, and
to also not fail if (for instance) there's a server already listening on port
8080
- Don't leak the listening socket / fds into the child process
- Fix warnings:
-- Remove argc/argv (-Wunused)
-- Mark sig __unused (-Wunused)
-- Mark quit static (-Wmissing-variable-declarations)
MFC after: 1 week
Sponsored by: EMC / Isilon Storage Division
Diffstat (limited to 'tools')
-rw-r--r-- | tools/regression/sockets/accept_fd_leak/Makefile | 4 | ||||
-rw-r--r-- | tools/regression/sockets/accept_fd_leak/accept_fd_leak.c | 50 |
2 files changed, 35 insertions, 19 deletions
diff --git a/tools/regression/sockets/accept_fd_leak/Makefile b/tools/regression/sockets/accept_fd_leak/Makefile index 208df0d..e9bfba6 100644 --- a/tools/regression/sockets/accept_fd_leak/Makefile +++ b/tools/regression/sockets/accept_fd_leak/Makefile @@ -4,8 +4,6 @@ PROG= accept_fd_leak MAN= - -regress: - ./accept_fd_leak +WARNS?= 6 .include <bsd.prog.mk> diff --git a/tools/regression/sockets/accept_fd_leak/accept_fd_leak.c b/tools/regression/sockets/accept_fd_leak/accept_fd_leak.c index 32d4edf..f2d3c0b 100644 --- a/tools/regression/sockets/accept_fd_leak/accept_fd_leak.c +++ b/tools/regression/sockets/accept_fd_leak/accept_fd_leak.c @@ -26,7 +26,7 @@ * $FreeBSD$ */ -#include <sys/types.h> +#include <sys/param.h> #include <sys/socket.h> #include <sys/wait.h> @@ -41,13 +41,16 @@ #include <string.h> #include <unistd.h> +#define BIND_ATTEMPTS 10 #define LOOPS 500 +#define NUM_ATTEMPTS 1000 -volatile int quit; +static volatile int quit; static void -child_died(int sig) +child_died(int sig __unused) { + quit = 1; } @@ -59,13 +62,12 @@ child_died(int sig) * briefly before beginning (not 100% reliable, but a good start). */ int -main(int argc, char *argv[]) +main(void) { struct sockaddr_in sin; socklen_t size; pid_t child; - int fd1, fd2, fd3, i, s; - int status; + int fd1, fd2, fd3, i, listen_port, s, status; printf("1..2\n"); @@ -85,10 +87,22 @@ main(int argc, char *argv[]) sin.sin_len = sizeof(sin); sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - sin.sin_port = htons(8080); - if (bind(s, (struct sockaddr *) &sin, sizeof(sin)) != 0) - errx(-1, "bind: %s", strerror(errno)); + srandomdev(); + + for (i = 0; i < BIND_ATTEMPTS; i++) { + /* Pick a random unprivileged port 1025-65535 */ + listen_port = MAX((int)random() % 65535, 1025); + sin.sin_port = htons(listen_port); + if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) == 0) + break; + warn("bind with %d failed", listen_port); + usleep(1000); + } + if (i >= BIND_ATTEMPTS) { + printf("Bail out!\n"); + exit(1); + } if (listen(s, -1) != 0) errx(-1, "listen: %s", strerror(errno)); @@ -134,16 +148,20 @@ main(int argc, char *argv[]) errx(-1, "fork: %s", strerror(errno)); /* - * Child process does 1000 connect's. + * Child process does `NUM_ATTEMPTS` connects. */ if (child == 0) { + close(fd1); + close(fd2); + close(s); + bzero(&sin, sizeof(sin)); sin.sin_len = sizeof(sin); sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - sin.sin_port = htons(8080); + sin.sin_port = htons(listen_port); - for (i = 0; i < 1000; i++) { + for (i = 0; i < NUM_ATTEMPTS; i++) { s = socket(PF_INET, SOCK_STREAM, 0); if (s == -1) errx(-1, "socket: %s", strerror(errno)); @@ -167,9 +185,9 @@ main(int argc, char *argv[]) errx(-1, "ioctl(F_GETFL): %s", strerror(errno)); if (i & O_NONBLOCK) errx(-1, "Failed to clear O_NONBLOCK (i=0x%x)\n", i); - - /* Do 1000 accept's with an invalid pointer. */ - for (i = 0; !quit && i < 1000; i++) { + + /* Do `NUM_ATTEMPTS` accepts with an invalid pointer. */ + for (i = 0; !quit && i < NUM_ATTEMPTS; i++) { size = sizeof(sin); if (accept(s, (struct sockaddr *)(uintptr_t)(0x100), &size) != -1) @@ -182,7 +200,7 @@ main(int argc, char *argv[]) errx(-1, "waitpid: %s", strerror(errno)); if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) warnx("child process died"); - + /* * Allocate a file descriptor and make sure it's fd2+2. 2 because * we allocate an fd for the socket. |