1c8c3fc56SRobert Watson /*- 2c8c3fc56SRobert Watson * Copyright (c) 2007 Robert N. M. Watson 3c8c3fc56SRobert Watson * All rights reserved. 4c8c3fc56SRobert Watson * 5c8c3fc56SRobert Watson * Redistribution and use in source and binary forms, with or without 6c8c3fc56SRobert Watson * modification, are permitted provided that the following conditions 7c8c3fc56SRobert Watson * are met: 8c8c3fc56SRobert Watson * 1. Redistributions of source code must retain the above copyright 9c8c3fc56SRobert Watson * notice, this list of conditions and the following disclaimer. 10c8c3fc56SRobert Watson * 2. Redistributions in binary form must reproduce the above copyright 11c8c3fc56SRobert Watson * notice, this list of conditions and the following disclaimer in the 12c8c3fc56SRobert Watson * documentation and/or other materials provided with the distribution. 13c8c3fc56SRobert Watson * 14c8c3fc56SRobert Watson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15c8c3fc56SRobert Watson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16c8c3fc56SRobert Watson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17c8c3fc56SRobert Watson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18c8c3fc56SRobert Watson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19c8c3fc56SRobert Watson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20c8c3fc56SRobert Watson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21c8c3fc56SRobert Watson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22c8c3fc56SRobert Watson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23c8c3fc56SRobert Watson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24c8c3fc56SRobert Watson * SUCH DAMAGE. 25c8c3fc56SRobert Watson * 26c8c3fc56SRobert Watson * $FreeBSD$ 27c8c3fc56SRobert Watson */ 28c8c3fc56SRobert Watson 29c8c3fc56SRobert Watson /* 30c8c3fc56SRobert Watson * A few regression tests for UNIX domain sockets. Run from single-user mode 31c8c3fc56SRobert Watson * as it checks the openfiles sysctl to look for leaks, and we don't want that 32c8c3fc56SRobert Watson * changing due to other processes doing stuff. 33c8c3fc56SRobert Watson */ 34c8c3fc56SRobert Watson 35c8c3fc56SRobert Watson #include <sys/types.h> 36c8c3fc56SRobert Watson #include <sys/signal.h> 37c8c3fc56SRobert Watson #include <sys/socket.h> 38c8c3fc56SRobert Watson #include <sys/sysctl.h> 39c8c3fc56SRobert Watson #include <sys/un.h> 40c8c3fc56SRobert Watson #include <sys/wait.h> 41c8c3fc56SRobert Watson 42c8c3fc56SRobert Watson #include <netinet/in.h> 43c8c3fc56SRobert Watson 44c8c3fc56SRobert Watson #include <err.h> 45c8c3fc56SRobert Watson #include <errno.h> 46c8c3fc56SRobert Watson #include <fcntl.h> 47c8c3fc56SRobert Watson #include <limits.h> 48c8c3fc56SRobert Watson #include <stdio.h> 49c8c3fc56SRobert Watson #include <stdlib.h> 50c8c3fc56SRobert Watson #include <string.h> 51c8c3fc56SRobert Watson #include <unistd.h> 52c8c3fc56SRobert Watson 53c8c3fc56SRobert Watson static int forcegc = 1; 54c8c3fc56SRobert Watson static char dpath[PATH_MAX]; 55c8c3fc56SRobert Watson static const char *test; 56c8c3fc56SRobert Watson 57c8c3fc56SRobert Watson static int 58*b0103260SKonstantin Belousov getsysctl(const char *name) 59c8c3fc56SRobert Watson { 60c8c3fc56SRobert Watson size_t len; 61c8c3fc56SRobert Watson int i; 62c8c3fc56SRobert Watson 63c8c3fc56SRobert Watson len = sizeof(i); 64*b0103260SKonstantin Belousov if (sysctlbyname(name, &i, &len, NULL, 0) < 0) 65*b0103260SKonstantin Belousov err(-1, "%s", name); 66c8c3fc56SRobert Watson return (i); 67c8c3fc56SRobert Watson } 68c8c3fc56SRobert Watson 69c8c3fc56SRobert Watson static int 70*b0103260SKonstantin Belousov getopenfiles(void) 71*b0103260SKonstantin Belousov { 72*b0103260SKonstantin Belousov 73*b0103260SKonstantin Belousov return (getsysctl("kern.openfiles")); 74*b0103260SKonstantin Belousov } 75*b0103260SKonstantin Belousov 76*b0103260SKonstantin Belousov static int 77c8c3fc56SRobert Watson getinflight(void) 78c8c3fc56SRobert Watson { 79c8c3fc56SRobert Watson 80*b0103260SKonstantin Belousov return (getsysctl("net.local.inflight")); 81*b0103260SKonstantin Belousov } 82*b0103260SKonstantin Belousov 83*b0103260SKonstantin Belousov static int 84*b0103260SKonstantin Belousov getdeferred(void) 85*b0103260SKonstantin Belousov { 86*b0103260SKonstantin Belousov 87*b0103260SKonstantin Belousov return (getsysctl("net.local.deferred")); 88c8c3fc56SRobert Watson } 89c8c3fc56SRobert Watson 90c8c3fc56SRobert Watson static void 91c8c3fc56SRobert Watson sendfd(int fd, int fdtosend) 92c8c3fc56SRobert Watson { 93c8c3fc56SRobert Watson struct msghdr mh; 94c8c3fc56SRobert Watson struct message { struct cmsghdr msg_hdr; int fd; } m; 95c8c3fc56SRobert Watson ssize_t len; 96c8c3fc56SRobert Watson int after_inflight, before_inflight; 97c8c3fc56SRobert Watson 98c8c3fc56SRobert Watson before_inflight = getinflight(); 99c8c3fc56SRobert Watson 100c8c3fc56SRobert Watson bzero(&mh, sizeof(mh)); 101c8c3fc56SRobert Watson bzero(&m, sizeof(m)); 102c8c3fc56SRobert Watson mh.msg_control = &m; 103c8c3fc56SRobert Watson mh.msg_controllen = sizeof(m); 104c8c3fc56SRobert Watson m.msg_hdr.cmsg_len = sizeof(m); 105c8c3fc56SRobert Watson m.msg_hdr.cmsg_level = SOL_SOCKET; 106c8c3fc56SRobert Watson m.msg_hdr.cmsg_type = SCM_RIGHTS; 107c8c3fc56SRobert Watson m.fd = fdtosend; 108c8c3fc56SRobert Watson len = sendmsg(fd, &mh, 0); 109c8c3fc56SRobert Watson if (len < 0) 110c8c3fc56SRobert Watson err(-1, "%s: sendmsg", test); 111c8c3fc56SRobert Watson after_inflight = getinflight(); 112c8c3fc56SRobert Watson if (after_inflight != before_inflight + 1) 113c8c3fc56SRobert Watson errx(-1, "%s: sendfd: before %d after %d\n", test, 114c8c3fc56SRobert Watson before_inflight, after_inflight); 115c8c3fc56SRobert Watson } 116c8c3fc56SRobert Watson 117c8c3fc56SRobert Watson static void 118c8c3fc56SRobert Watson close2(int fd1, int fd2) 119c8c3fc56SRobert Watson { 120c8c3fc56SRobert Watson 121c8c3fc56SRobert Watson close(fd1); 122c8c3fc56SRobert Watson close(fd2); 123c8c3fc56SRobert Watson } 124c8c3fc56SRobert Watson 125c8c3fc56SRobert Watson static void 126c8c3fc56SRobert Watson close3(int fd1, int fd2, int fd3) 127c8c3fc56SRobert Watson { 128c8c3fc56SRobert Watson 129c8c3fc56SRobert Watson close2(fd1, fd2); 130c8c3fc56SRobert Watson close(fd3); 131c8c3fc56SRobert Watson } 132c8c3fc56SRobert Watson 133c8c3fc56SRobert Watson static void 134c8c3fc56SRobert Watson close4(int fd1, int fd2, int fd3, int fd4) 135c8c3fc56SRobert Watson { 136c8c3fc56SRobert Watson 137c8c3fc56SRobert Watson close2(fd1, fd2); 138c8c3fc56SRobert Watson close2(fd3, fd4); 139c8c3fc56SRobert Watson } 140c8c3fc56SRobert Watson 141c8c3fc56SRobert Watson static void 142c8c3fc56SRobert Watson close5(int fd1, int fd2, int fd3, int fd4, int fd5) 143c8c3fc56SRobert Watson { 144c8c3fc56SRobert Watson 145c8c3fc56SRobert Watson close3(fd1, fd2, fd3); 146c8c3fc56SRobert Watson close2(fd4, fd5); 147c8c3fc56SRobert Watson } 148c8c3fc56SRobert Watson 149c8c3fc56SRobert Watson static int 150c8c3fc56SRobert Watson my_socket(int domain, int type, int proto) 151c8c3fc56SRobert Watson { 152c8c3fc56SRobert Watson int sock; 153c8c3fc56SRobert Watson 154c8c3fc56SRobert Watson sock = socket(domain, type, proto); 155c8c3fc56SRobert Watson if (sock < 0) 156c8c3fc56SRobert Watson err(-1, "%s: socket", test); 157c8c3fc56SRobert Watson return (sock); 158c8c3fc56SRobert Watson } 159c8c3fc56SRobert Watson 160c8c3fc56SRobert Watson static void 161c8c3fc56SRobert Watson my_bind(int sock, struct sockaddr *sa, socklen_t len) 162c8c3fc56SRobert Watson { 163c8c3fc56SRobert Watson 164c8c3fc56SRobert Watson if (bind(sock, sa, len) < 0) 165c8c3fc56SRobert Watson err(-1, "%s: bind", test); 166c8c3fc56SRobert Watson } 167c8c3fc56SRobert Watson 168c8c3fc56SRobert Watson static void 169c8c3fc56SRobert Watson my_connect(int sock, struct sockaddr *sa, socklen_t len) 170c8c3fc56SRobert Watson { 171c8c3fc56SRobert Watson 1720ca4746bSRobert Watson if (connect(sock, sa, len) < 0 && errno != EINPROGRESS) 173c8c3fc56SRobert Watson err(-1, "%s: connect", test); 174c8c3fc56SRobert Watson } 175c8c3fc56SRobert Watson 176c8c3fc56SRobert Watson static void 177c8c3fc56SRobert Watson my_listen(int sock, int backlog) 178c8c3fc56SRobert Watson { 179c8c3fc56SRobert Watson 180c8c3fc56SRobert Watson if (listen(sock, backlog) < 0) 181c8c3fc56SRobert Watson err(-1, "%s: listen", test); 182c8c3fc56SRobert Watson } 183c8c3fc56SRobert Watson 184c8c3fc56SRobert Watson static void 185c8c3fc56SRobert Watson my_socketpair(int *sv) 186c8c3fc56SRobert Watson { 187c8c3fc56SRobert Watson 188c8c3fc56SRobert Watson if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) < 0) 189c8c3fc56SRobert Watson err(-1, "%s: socketpair", test); 190c8c3fc56SRobert Watson } 191c8c3fc56SRobert Watson 192c8c3fc56SRobert Watson static void 193c8c3fc56SRobert Watson my_getsockname(int s, struct sockaddr *sa, socklen_t *salen) 194c8c3fc56SRobert Watson { 195c8c3fc56SRobert Watson 196c8c3fc56SRobert Watson if (getsockname(s, sa, salen) < 0) 197c8c3fc56SRobert Watson err(-1, "%s: getsockname", test); 198c8c3fc56SRobert Watson } 199c8c3fc56SRobert Watson 200c8c3fc56SRobert Watson static void 201c8c3fc56SRobert Watson setnonblock(int s) 202c8c3fc56SRobert Watson { 203c8c3fc56SRobert Watson 204c8c3fc56SRobert Watson if (fcntl(s, F_SETFL, O_NONBLOCK) < 0) 205c8c3fc56SRobert Watson err(-1, "%s: fcntl(F_SETFL, O_NONBLOCK)", test); 206c8c3fc56SRobert Watson } 207c8c3fc56SRobert Watson 208c8c3fc56SRobert Watson static void 209c8c3fc56SRobert Watson alloc3fds(int *s, int *sv) 210c8c3fc56SRobert Watson { 211c8c3fc56SRobert Watson 212c8c3fc56SRobert Watson if ((*s = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) 213c8c3fc56SRobert Watson err(-1, "%s: socket", test); 214c8c3fc56SRobert Watson if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) < 0) 215c8c3fc56SRobert Watson err(-1, "%s: socketpair", test); 216c8c3fc56SRobert Watson } 217c8c3fc56SRobert Watson 218c8c3fc56SRobert Watson static void 219c8c3fc56SRobert Watson alloc5fds(int *s, int *sva, int *svb) 220c8c3fc56SRobert Watson { 221c8c3fc56SRobert Watson 222c8c3fc56SRobert Watson if ((*s = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) 223c8c3fc56SRobert Watson err(-1, "%s: socket", test); 224c8c3fc56SRobert Watson if (socketpair(PF_UNIX, SOCK_STREAM, 0, sva) < 0) 225c8c3fc56SRobert Watson err(-1, "%s: socketpair", test); 226c8c3fc56SRobert Watson if (socketpair(PF_UNIX, SOCK_STREAM, 0, svb) < 0) 227c8c3fc56SRobert Watson err(-1, "%s: socketpair", test); 228c8c3fc56SRobert Watson } 229c8c3fc56SRobert Watson 230c8c3fc56SRobert Watson static void 231c8c3fc56SRobert Watson save_sysctls(int *before_inflight, int *before_openfiles) 232c8c3fc56SRobert Watson { 233c8c3fc56SRobert Watson 234c8c3fc56SRobert Watson *before_inflight = getinflight(); 235c8c3fc56SRobert Watson *before_openfiles = getopenfiles(); 236c8c3fc56SRobert Watson } 237c8c3fc56SRobert Watson 238c8c3fc56SRobert Watson /* 239c8c3fc56SRobert Watson * Try hard to make sure that the GC does in fact run before we test the 240c8c3fc56SRobert Watson * condition of things. 241c8c3fc56SRobert Watson */ 242c8c3fc56SRobert Watson static void 243c8c3fc56SRobert Watson trigger_gc(void) 244c8c3fc56SRobert Watson { 245c8c3fc56SRobert Watson int s; 246c8c3fc56SRobert Watson 247c8c3fc56SRobert Watson if (forcegc) { 248c8c3fc56SRobert Watson if ((s = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) 249c8c3fc56SRobert Watson err(-1, "trigger_gc: socket"); 250c8c3fc56SRobert Watson close(s); 251c8c3fc56SRobert Watson } 252c8c3fc56SRobert Watson sleep(1); 253c8c3fc56SRobert Watson } 254c8c3fc56SRobert Watson 255c8c3fc56SRobert Watson static void 256c8c3fc56SRobert Watson test_sysctls(int before_inflight, int before_openfiles) 257c8c3fc56SRobert Watson { 258c8c3fc56SRobert Watson int after_inflight, after_openfiles; 259c8c3fc56SRobert Watson 260c8c3fc56SRobert Watson trigger_gc(); 261c8c3fc56SRobert Watson after_inflight = getinflight(); 262c8c3fc56SRobert Watson if (after_inflight != before_inflight) 263c8c3fc56SRobert Watson warnx("%s: before inflight: %d, after inflight: %d", 264c8c3fc56SRobert Watson test, before_inflight, after_inflight); 265c8c3fc56SRobert Watson 266c8c3fc56SRobert Watson after_openfiles = getopenfiles(); 267c8c3fc56SRobert Watson if (after_openfiles != before_openfiles) 268c8c3fc56SRobert Watson warnx("%s: before: %d, after: %d", test, before_openfiles, 269c8c3fc56SRobert Watson after_openfiles); 270c8c3fc56SRobert Watson } 271c8c3fc56SRobert Watson 272c8c3fc56SRobert Watson static void 273c8c3fc56SRobert Watson twosome_nothing(void) 274c8c3fc56SRobert Watson { 275c8c3fc56SRobert Watson int inflight, openfiles; 276c8c3fc56SRobert Watson int sv[2]; 277c8c3fc56SRobert Watson 278c8c3fc56SRobert Watson /* 279c8c3fc56SRobert Watson * Create a pair, close in one order. 280c8c3fc56SRobert Watson */ 281c8c3fc56SRobert Watson test = "twosome_nothing1"; 282c8c3fc56SRobert Watson printf("%s\n", test); 283c8c3fc56SRobert Watson save_sysctls(&inflight, &openfiles); 284c8c3fc56SRobert Watson my_socketpair(sv); 285c8c3fc56SRobert Watson close2(sv[0], sv[1]); 286c8c3fc56SRobert Watson test_sysctls(inflight, openfiles); 287c8c3fc56SRobert Watson 288c8c3fc56SRobert Watson /* 289c8c3fc56SRobert Watson * Create a pair, close in the other order. 290c8c3fc56SRobert Watson */ 291c8c3fc56SRobert Watson test = "twosome_nothing2"; 292c8c3fc56SRobert Watson printf("%s\n", test); 293c8c3fc56SRobert Watson save_sysctls(&inflight, &openfiles); 294c8c3fc56SRobert Watson my_socketpair(sv); 295c8c3fc56SRobert Watson close2(sv[0], sv[1]); 296c8c3fc56SRobert Watson test_sysctls(inflight, openfiles); 297c8c3fc56SRobert Watson } 298c8c3fc56SRobert Watson 299c8c3fc56SRobert Watson /* 300c8c3fc56SRobert Watson * Using a socket pair, send various endpoints over the pair and close in 301c8c3fc56SRobert Watson * various orders. 302c8c3fc56SRobert Watson */ 303c8c3fc56SRobert Watson static void 304c8c3fc56SRobert Watson twosome_drop_work(const char *testname, int sendvia, int tosend, int closefirst) 305c8c3fc56SRobert Watson { 306c8c3fc56SRobert Watson int inflight, openfiles; 307c8c3fc56SRobert Watson int sv[2]; 308c8c3fc56SRobert Watson 309c8c3fc56SRobert Watson printf("%s\n", testname); 310c8c3fc56SRobert Watson test = testname; 311c8c3fc56SRobert Watson save_sysctls(&inflight, &openfiles); 312c8c3fc56SRobert Watson my_socketpair(sv); 313c8c3fc56SRobert Watson sendfd(sv[sendvia], sv[tosend]); 314c8c3fc56SRobert Watson if (closefirst == 0) 315c8c3fc56SRobert Watson close2(sv[0], sv[1]); 316c8c3fc56SRobert Watson else 317c8c3fc56SRobert Watson close2(sv[1], sv[0]); 318c8c3fc56SRobert Watson test_sysctls(inflight, openfiles); 319c8c3fc56SRobert Watson } 320c8c3fc56SRobert Watson 321c8c3fc56SRobert Watson static void 322c8c3fc56SRobert Watson twosome_drop(void) 323c8c3fc56SRobert Watson { 324c8c3fc56SRobert Watson 325c8c3fc56SRobert Watson /* 326c8c3fc56SRobert Watson * In various combations, some wastefully symmetric, create socket 327c8c3fc56SRobert Watson * pairs and send one or another endpoint over one or another 328c8c3fc56SRobert Watson * endpoint, closing the endpoints in various orders. 329c8c3fc56SRobert Watson */ 330c8c3fc56SRobert Watson twosome_drop_work("twosome_drop1", 0, 0, 0); 331c8c3fc56SRobert Watson twosome_drop_work("twosome_drop2", 0, 0, 1); 332c8c3fc56SRobert Watson twosome_drop_work("twosome_drop3", 0, 1, 0); 333c8c3fc56SRobert Watson twosome_drop_work("twosome_drop4", 0, 1, 1); 334c8c3fc56SRobert Watson twosome_drop_work("twosome_drop5", 1, 0, 0); 335c8c3fc56SRobert Watson twosome_drop_work("twosome_drop6", 1, 0, 1); 336c8c3fc56SRobert Watson twosome_drop_work("twosome_drop7", 1, 1, 0); 337c8c3fc56SRobert Watson twosome_drop_work("twosome_drop8", 1, 1, 1); 338c8c3fc56SRobert Watson } 339c8c3fc56SRobert Watson 340c8c3fc56SRobert Watson static void 341c8c3fc56SRobert Watson threesome_nothing(void) 342c8c3fc56SRobert Watson { 343c8c3fc56SRobert Watson int inflight, openfiles; 344c8c3fc56SRobert Watson int s, sv[2]; 345c8c3fc56SRobert Watson 346c8c3fc56SRobert Watson test = "threesome_nothing"; 347c8c3fc56SRobert Watson printf("%s\n", test); 348c8c3fc56SRobert Watson save_sysctls(&inflight, &openfiles); 349c8c3fc56SRobert Watson alloc3fds(&s, sv); 350c8c3fc56SRobert Watson close3(s, sv[0], sv[1]); 351c8c3fc56SRobert Watson test_sysctls(inflight, openfiles); 352c8c3fc56SRobert Watson } 353c8c3fc56SRobert Watson 354c8c3fc56SRobert Watson /* 355c8c3fc56SRobert Watson * threesome_drop: create a pair and a spare, send the spare over the pair, and 356c8c3fc56SRobert Watson * close in various orders and make sure all the fds went away. 357c8c3fc56SRobert Watson */ 358c8c3fc56SRobert Watson static void 359c8c3fc56SRobert Watson threesome_drop(void) 360c8c3fc56SRobert Watson { 361c8c3fc56SRobert Watson int inflight, openfiles; 362c8c3fc56SRobert Watson int s, sv[2]; 363c8c3fc56SRobert Watson 364c8c3fc56SRobert Watson /* 365c8c3fc56SRobert Watson * threesome_drop1: close sent send receive 366c8c3fc56SRobert Watson */ 367c8c3fc56SRobert Watson test = "threesome_drop1"; 368c8c3fc56SRobert Watson printf("%s\n", test); 369c8c3fc56SRobert Watson save_sysctls(&inflight, &openfiles); 370c8c3fc56SRobert Watson alloc3fds(&s, sv); 371c8c3fc56SRobert Watson sendfd(sv[0], s); 372c8c3fc56SRobert Watson close3(s, sv[0], sv[1]); 373c8c3fc56SRobert Watson test_sysctls(inflight, openfiles); 374c8c3fc56SRobert Watson 375c8c3fc56SRobert Watson /* 376c8c3fc56SRobert Watson * threesome_drop2: close sent receive send 377c8c3fc56SRobert Watson */ 378c8c3fc56SRobert Watson test = "threesome_drop2"; 379c8c3fc56SRobert Watson printf("%s\n", test); 380c8c3fc56SRobert Watson save_sysctls(&inflight, &openfiles); 381c8c3fc56SRobert Watson alloc3fds(&s, sv); 382c8c3fc56SRobert Watson sendfd(sv[0], s); 383c8c3fc56SRobert Watson close3(s, sv[1], sv[0]); 384c8c3fc56SRobert Watson test_sysctls(inflight, openfiles); 385c8c3fc56SRobert Watson 386c8c3fc56SRobert Watson /* 387c8c3fc56SRobert Watson * threesome_drop3: close receive sent send 388c8c3fc56SRobert Watson */ 389c8c3fc56SRobert Watson test = "threesome_drop3"; 390c8c3fc56SRobert Watson printf("%s\n", test); 391c8c3fc56SRobert Watson save_sysctls(&inflight, &openfiles); 392c8c3fc56SRobert Watson alloc3fds(&s, sv); 393c8c3fc56SRobert Watson sendfd(sv[0], s); 394c8c3fc56SRobert Watson close3(sv[1], s, sv[0]); 395c8c3fc56SRobert Watson test_sysctls(inflight, openfiles); 396c8c3fc56SRobert Watson 397c8c3fc56SRobert Watson /* 398c8c3fc56SRobert Watson * threesome_drop4: close receive send sent 399c8c3fc56SRobert Watson */ 400c8c3fc56SRobert Watson test = "threesome_drop4"; 401c8c3fc56SRobert Watson printf("%s\n", test); 402c8c3fc56SRobert Watson save_sysctls(&inflight, &openfiles); 403c8c3fc56SRobert Watson alloc3fds(&s, sv); 404c8c3fc56SRobert Watson sendfd(sv[0], s); 405c8c3fc56SRobert Watson close3(sv[1], sv[0], s); 406c8c3fc56SRobert Watson test_sysctls(inflight, openfiles); 407c8c3fc56SRobert Watson 408c8c3fc56SRobert Watson /* 409c8c3fc56SRobert Watson * threesome_drop5: close send receive sent 410c8c3fc56SRobert Watson */ 411c8c3fc56SRobert Watson test = "threesome_drop5"; 412c8c3fc56SRobert Watson printf("%s\n", test); 413c8c3fc56SRobert Watson save_sysctls(&inflight, &openfiles); 414c8c3fc56SRobert Watson alloc3fds(&s, sv); 415c8c3fc56SRobert Watson sendfd(sv[0], s); 416c8c3fc56SRobert Watson close3(sv[0], sv[1], s); 417c8c3fc56SRobert Watson test_sysctls(inflight, openfiles); 418c8c3fc56SRobert Watson 419c8c3fc56SRobert Watson /* 420c8c3fc56SRobert Watson * threesome_drop6: close send sent receive 421c8c3fc56SRobert Watson */ 422c8c3fc56SRobert Watson test = "threesome_drop6"; 423c8c3fc56SRobert Watson printf("%s\n", test); 424c8c3fc56SRobert Watson save_sysctls(&inflight, &openfiles); 425c8c3fc56SRobert Watson alloc3fds(&s, sv); 426c8c3fc56SRobert Watson close3(sv[0], s, sv[1]); 427c8c3fc56SRobert Watson test_sysctls(inflight, openfiles); 428c8c3fc56SRobert Watson } 429c8c3fc56SRobert Watson 430c8c3fc56SRobert Watson /* 431c8c3fc56SRobert Watson * Fivesome tests: create two socket pairs and a spare, send the spare over 432c8c3fc56SRobert Watson * the first socket pair, then send the first socket pair over the second 433c8c3fc56SRobert Watson * socket pair, and GC. Do various closes at various points to exercise 434c8c3fc56SRobert Watson * various cases. 435c8c3fc56SRobert Watson */ 436c8c3fc56SRobert Watson static void 437c8c3fc56SRobert Watson fivesome_nothing(void) 438c8c3fc56SRobert Watson { 439c8c3fc56SRobert Watson int inflight, openfiles; 440c8c3fc56SRobert Watson int spare, sva[2], svb[2]; 441c8c3fc56SRobert Watson 442c8c3fc56SRobert Watson test = "fivesome_nothing"; 443c8c3fc56SRobert Watson printf("%s\n", test); 444c8c3fc56SRobert Watson save_sysctls(&inflight, &openfiles); 445c8c3fc56SRobert Watson alloc5fds(&spare, sva, svb); 446c8c3fc56SRobert Watson close5(spare, sva[0], sva[1], svb[0], svb[1]); 447c8c3fc56SRobert Watson test_sysctls(inflight, openfiles); 448c8c3fc56SRobert Watson } 449c8c3fc56SRobert Watson 450c8c3fc56SRobert Watson static void 451c8c3fc56SRobert Watson fivesome_drop_work(const char *testname, int close_spare_after_send, 452c8c3fc56SRobert Watson int close_sva_after_send) 453c8c3fc56SRobert Watson { 454c8c3fc56SRobert Watson int inflight, openfiles; 455c8c3fc56SRobert Watson int spare, sva[2], svb[2]; 456c8c3fc56SRobert Watson 457c8c3fc56SRobert Watson printf("%s\n", testname); 458c8c3fc56SRobert Watson test = testname; 459c8c3fc56SRobert Watson save_sysctls(&inflight, &openfiles); 460c8c3fc56SRobert Watson alloc5fds(&spare, sva, svb); 461c8c3fc56SRobert Watson 462c8c3fc56SRobert Watson /* 463c8c3fc56SRobert Watson * Send spare over sva. 464c8c3fc56SRobert Watson */ 465c8c3fc56SRobert Watson sendfd(sva[0], spare); 466c8c3fc56SRobert Watson if (close_spare_after_send) 467c8c3fc56SRobert Watson close(spare); 468c8c3fc56SRobert Watson 469c8c3fc56SRobert Watson /* 470c8c3fc56SRobert Watson * Send sva over svb. 471c8c3fc56SRobert Watson */ 472c8c3fc56SRobert Watson sendfd(svb[0], sva[0]); 473c8c3fc56SRobert Watson sendfd(svb[0], sva[1]); 474c8c3fc56SRobert Watson if (close_sva_after_send) 475c8c3fc56SRobert Watson close2(sva[0], sva[1]); 476c8c3fc56SRobert Watson 477c8c3fc56SRobert Watson close2(svb[0], svb[1]); 478c8c3fc56SRobert Watson 479c8c3fc56SRobert Watson if (!close_sva_after_send) 480c8c3fc56SRobert Watson close2(sva[0], sva[1]); 481c8c3fc56SRobert Watson if (!close_spare_after_send) 482c8c3fc56SRobert Watson close(spare); 483c8c3fc56SRobert Watson 484c8c3fc56SRobert Watson test_sysctls(inflight, openfiles); 485c8c3fc56SRobert Watson } 486c8c3fc56SRobert Watson 487c8c3fc56SRobert Watson static void 488c8c3fc56SRobert Watson fivesome_drop(void) 489c8c3fc56SRobert Watson { 490c8c3fc56SRobert Watson 491c8c3fc56SRobert Watson fivesome_drop_work("fivesome_drop1", 0, 0); 492c8c3fc56SRobert Watson fivesome_drop_work("fivesome_drop2", 0, 1); 493c8c3fc56SRobert Watson fivesome_drop_work("fivesome_drop3", 1, 0); 494c8c3fc56SRobert Watson fivesome_drop_work("fivesome_drop4", 1, 1); 495c8c3fc56SRobert Watson } 496c8c3fc56SRobert Watson 497c8c3fc56SRobert Watson /* 498c8c3fc56SRobert Watson * Create a somewhat nasty dual-socket socket intended to upset the garbage 499c8c3fc56SRobert Watson * collector if mark-and-sweep is wrong. 500c8c3fc56SRobert Watson */ 501c8c3fc56SRobert Watson static void 502c8c3fc56SRobert Watson complex_cycles(void) 503c8c3fc56SRobert Watson { 504c8c3fc56SRobert Watson int inflight, openfiles; 505c8c3fc56SRobert Watson int spare, sva[2], svb[2]; 506c8c3fc56SRobert Watson 507c8c3fc56SRobert Watson test = "complex_cycles"; 508c8c3fc56SRobert Watson printf("%s\n", test); 509c8c3fc56SRobert Watson save_sysctls(&inflight, &openfiles); 510c8c3fc56SRobert Watson alloc5fds(&spare, sva, svb); 511c8c3fc56SRobert Watson sendfd(sva[0], svb[0]); 512c8c3fc56SRobert Watson sendfd(sva[0], svb[1]); 513c8c3fc56SRobert Watson sendfd(svb[0], sva[0]); 514c8c3fc56SRobert Watson sendfd(svb[0], sva[1]); 515c8c3fc56SRobert Watson sendfd(svb[0], spare); 516c8c3fc56SRobert Watson sendfd(sva[0], spare); 517c8c3fc56SRobert Watson close5(spare, sva[0], sva[1], svb[0], svb[1]); 518c8c3fc56SRobert Watson test_sysctls(inflight, openfiles); 519c8c3fc56SRobert Watson } 520c8c3fc56SRobert Watson 521c8c3fc56SRobert Watson /* 522c8c3fc56SRobert Watson * Listen sockets can also be passed over UNIX domain sockets, so test 523c8c3fc56SRobert Watson * various cases, including ones where listen sockets have waiting sockets 524c8c3fc56SRobert Watson * hanging off them... 525c8c3fc56SRobert Watson */ 526c8c3fc56SRobert Watson static void 527c8c3fc56SRobert Watson listen_nothing(void) 528c8c3fc56SRobert Watson { 529c8c3fc56SRobert Watson struct sockaddr_un sun; 530c8c3fc56SRobert Watson struct sockaddr_in sin; 531c8c3fc56SRobert Watson int inflight, openfiles; 532c8c3fc56SRobert Watson int s; 533c8c3fc56SRobert Watson 534c8c3fc56SRobert Watson test = "listen_nothing_unp"; 535c8c3fc56SRobert Watson printf("%s\n", test); 536c8c3fc56SRobert Watson bzero(&sun, sizeof(sun)); 537c8c3fc56SRobert Watson sun.sun_family = AF_LOCAL; 538c8c3fc56SRobert Watson sun.sun_len = sizeof(sun); 539c8c3fc56SRobert Watson snprintf(sun.sun_path, sizeof(sun.sun_path), "%s/%s", dpath, test); 540c8c3fc56SRobert Watson save_sysctls(&inflight, &openfiles); 541c8c3fc56SRobert Watson s = my_socket(PF_LOCAL, SOCK_STREAM, 0); 542c8c3fc56SRobert Watson my_bind(s, (struct sockaddr *)&sun, sizeof(sun)); 543c8c3fc56SRobert Watson my_listen(s, -1); 544c8c3fc56SRobert Watson close(s); 545c8c3fc56SRobert Watson (void)unlink(sun.sun_path); 546c8c3fc56SRobert Watson test_sysctls(inflight, openfiles); 547c8c3fc56SRobert Watson 548c8c3fc56SRobert Watson test = "listen_nothing_inet"; 549c8c3fc56SRobert Watson printf("%s\n", test); 550c8c3fc56SRobert Watson bzero(&sin, sizeof(sin)); 551c8c3fc56SRobert Watson sin.sin_family = AF_INET; 552c8c3fc56SRobert Watson sin.sin_len = sizeof(sin); 553c8c3fc56SRobert Watson sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 554c8c3fc56SRobert Watson sin.sin_port = htons(0); 555c8c3fc56SRobert Watson save_sysctls(&inflight, &openfiles); 556c8c3fc56SRobert Watson s = my_socket(PF_INET, SOCK_STREAM, 0); 557c8c3fc56SRobert Watson my_bind(s, (struct sockaddr *)&sin, sizeof(sin)); 558c8c3fc56SRobert Watson my_listen(s, -1); 559c8c3fc56SRobert Watson close(s); 560c8c3fc56SRobert Watson test_sysctls(inflight, openfiles); 561c8c3fc56SRobert Watson } 562c8c3fc56SRobert Watson 563c8c3fc56SRobert Watson /* 564c8c3fc56SRobert Watson * Send a listen UDP socket over a UNIX domain socket. 565c8c3fc56SRobert Watson * 566c8c3fc56SRobert Watson * Send a listen TCP socket over a UNIX domain socket. 567c8c3fc56SRobert Watson * 568c8c3fc56SRobert Watson * Do each twice, with closing of the listen socket vs. socketpair in 569c8c3fc56SRobert Watson * different orders. 570c8c3fc56SRobert Watson */ 571c8c3fc56SRobert Watson static void 572c8c3fc56SRobert Watson listen_drop(void) 573c8c3fc56SRobert Watson { 574c8c3fc56SRobert Watson struct sockaddr_un sun; 575c8c3fc56SRobert Watson struct sockaddr_in sin; 576c8c3fc56SRobert Watson int inflight, openfiles; 577c8c3fc56SRobert Watson int s, sv[2]; 578c8c3fc56SRobert Watson 579c8c3fc56SRobert Watson bzero(&sun, sizeof(sun)); 580c8c3fc56SRobert Watson sun.sun_family = AF_LOCAL; 581c8c3fc56SRobert Watson sun.sun_len = sizeof(sun); 582c8c3fc56SRobert Watson 583c8c3fc56SRobert Watson /* 584c8c3fc56SRobert Watson * Close listen socket first. 585c8c3fc56SRobert Watson */ 586c8c3fc56SRobert Watson test = "listen_drop_unp1"; 587c8c3fc56SRobert Watson printf("%s\n", test); 588c8c3fc56SRobert Watson snprintf(sun.sun_path, sizeof(sun.sun_path), "%s/%s", dpath, test); 589c8c3fc56SRobert Watson save_sysctls(&inflight, &openfiles); 590c8c3fc56SRobert Watson s = my_socket(PF_LOCAL, SOCK_STREAM, 0); 591c8c3fc56SRobert Watson my_bind(s, (struct sockaddr *)&sun, sizeof(sun)); 592c8c3fc56SRobert Watson my_listen(s, -1); 593c8c3fc56SRobert Watson my_socketpair(sv); 594c8c3fc56SRobert Watson sendfd(sv[0], s); 595c8c3fc56SRobert Watson close3(s, sv[0], sv[1]); 596c8c3fc56SRobert Watson test_sysctls(inflight, openfiles); 597c8c3fc56SRobert Watson 598c8c3fc56SRobert Watson /* 599c8c3fc56SRobert Watson * Close socketpair first. 600c8c3fc56SRobert Watson */ 601c8c3fc56SRobert Watson test = "listen_drop_unp2"; 602c8c3fc56SRobert Watson printf("%s\n", test); 603c8c3fc56SRobert Watson snprintf(sun.sun_path, sizeof(sun.sun_path), "%s/%s", dpath, test); 604c8c3fc56SRobert Watson save_sysctls(&inflight, &openfiles); 605c8c3fc56SRobert Watson s = my_socket(PF_LOCAL, SOCK_STREAM, 0); 606c8c3fc56SRobert Watson my_bind(s, (struct sockaddr *)&sun, sizeof(sun)); 607c8c3fc56SRobert Watson my_listen(s, -1); 608c8c3fc56SRobert Watson my_socketpair(sv); 609c8c3fc56SRobert Watson sendfd(sv[0], s); 610c8c3fc56SRobert Watson close3(sv[0], sv[1], s); 611c8c3fc56SRobert Watson test_sysctls(inflight, openfiles); 612c8c3fc56SRobert Watson 613c8c3fc56SRobert Watson sin.sin_family = AF_INET; 614c8c3fc56SRobert Watson sin.sin_len = sizeof(sin); 615c8c3fc56SRobert Watson sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 616c8c3fc56SRobert Watson sin.sin_port = htons(0); 617c8c3fc56SRobert Watson 618c8c3fc56SRobert Watson /* 619c8c3fc56SRobert Watson * Close listen socket first. 620c8c3fc56SRobert Watson */ 621c8c3fc56SRobert Watson test = "listen_drop_inet1"; 622c8c3fc56SRobert Watson printf("%s\n", test); 623c8c3fc56SRobert Watson bzero(&sun, sizeof(sun)); 624c8c3fc56SRobert Watson save_sysctls(&inflight, &openfiles); 625c8c3fc56SRobert Watson s = my_socket(PF_INET, SOCK_STREAM, 0); 626c8c3fc56SRobert Watson my_bind(s, (struct sockaddr *)&sin, sizeof(sin)); 627c8c3fc56SRobert Watson my_listen(s, -1); 628c8c3fc56SRobert Watson my_socketpair(sv); 629c8c3fc56SRobert Watson sendfd(sv[0], s); 630c8c3fc56SRobert Watson close3(s, sv[0], sv[1]); 631c8c3fc56SRobert Watson test_sysctls(inflight, openfiles); 632c8c3fc56SRobert Watson 633c8c3fc56SRobert Watson /* 634c8c3fc56SRobert Watson * Close socketpair first. 635c8c3fc56SRobert Watson */ 636c8c3fc56SRobert Watson test = "listen_drop_inet2"; 637c8c3fc56SRobert Watson printf("%s\n", test); 638c8c3fc56SRobert Watson bzero(&sun, sizeof(sun)); 639c8c3fc56SRobert Watson save_sysctls(&inflight, &openfiles); 640c8c3fc56SRobert Watson s = my_socket(PF_INET, SOCK_STREAM, 0); 641c8c3fc56SRobert Watson my_bind(s, (struct sockaddr *)&sin, sizeof(sin)); 642c8c3fc56SRobert Watson my_listen(s, -1); 643c8c3fc56SRobert Watson my_socketpair(sv); 644c8c3fc56SRobert Watson sendfd(sv[0], s); 645c8c3fc56SRobert Watson close3(sv[0], sv[1], s); 646c8c3fc56SRobert Watson test_sysctls(inflight, openfiles); 647c8c3fc56SRobert Watson } 648c8c3fc56SRobert Watson 649c8c3fc56SRobert Watson /* 650c8c3fc56SRobert Watson * Up things a notch with listen sockets: add connections that can be 651c8c3fc56SRobert Watson * accepted to the listen queues. 652c8c3fc56SRobert Watson */ 653c8c3fc56SRobert Watson static void 654c8c3fc56SRobert Watson listen_connect_nothing(void) 655c8c3fc56SRobert Watson { 656c8c3fc56SRobert Watson struct sockaddr_in sin; 657c8c3fc56SRobert Watson int slisten, sconnect, sv[2]; 658c8c3fc56SRobert Watson int inflight, openfiles; 659c8c3fc56SRobert Watson socklen_t len; 660c8c3fc56SRobert Watson 661c8c3fc56SRobert Watson test = "listen_connect_nothing"; 662c8c3fc56SRobert Watson printf("%s\n", test); 663c8c3fc56SRobert Watson save_sysctls(&inflight, &openfiles); 664c8c3fc56SRobert Watson 665c8c3fc56SRobert Watson slisten = my_socket(PF_INET, SOCK_STREAM, 0); 666c8c3fc56SRobert Watson my_bind(slisten, (struct sockaddr *)&sin, sizeof(sin)); 667c8c3fc56SRobert Watson my_listen(slisten, -1); 668c8c3fc56SRobert Watson 669c8c3fc56SRobert Watson my_socketpair(sv); 670c8c3fc56SRobert Watson 671c8c3fc56SRobert Watson len = sizeof(sin); 672c8c3fc56SRobert Watson my_getsockname(slisten, (struct sockaddr *)&sin, &len); 673c8c3fc56SRobert Watson 674c8c3fc56SRobert Watson sconnect = my_socket(PF_INET, SOCK_STREAM, 0); 675c8c3fc56SRobert Watson setnonblock(sconnect); 676c8c3fc56SRobert Watson my_connect(sconnect, (struct sockaddr *)&sin, len); 677c8c3fc56SRobert Watson 678c8c3fc56SRobert Watson sleep(1); 679c8c3fc56SRobert Watson 680c8c3fc56SRobert Watson close4(slisten, sconnect, sv[0], sv[1]); 681c8c3fc56SRobert Watson 682c8c3fc56SRobert Watson test_sysctls(inflight, openfiles); 683c8c3fc56SRobert Watson } 684c8c3fc56SRobert Watson 685c8c3fc56SRobert Watson static void 686c8c3fc56SRobert Watson listen_connect_drop(void) 687c8c3fc56SRobert Watson { 688c8c3fc56SRobert Watson struct sockaddr_in sin; 689c8c3fc56SRobert Watson int slisten, sconnect, sv[2]; 690c8c3fc56SRobert Watson int inflight, openfiles; 691c8c3fc56SRobert Watson socklen_t len; 692c8c3fc56SRobert Watson 693c8c3fc56SRobert Watson test = "listen_connect_drop"; 694c8c3fc56SRobert Watson printf("%s\n", test); 695c8c3fc56SRobert Watson save_sysctls(&inflight, &openfiles); 696c8c3fc56SRobert Watson 697c8c3fc56SRobert Watson slisten = my_socket(PF_INET, SOCK_STREAM, 0); 698c8c3fc56SRobert Watson my_bind(slisten, (struct sockaddr *)&sin, sizeof(sin)); 699c8c3fc56SRobert Watson my_listen(slisten, -1); 700c8c3fc56SRobert Watson 701c8c3fc56SRobert Watson my_socketpair(sv); 702c8c3fc56SRobert Watson 703c8c3fc56SRobert Watson len = sizeof(sin); 704c8c3fc56SRobert Watson my_getsockname(slisten, (struct sockaddr *)&sin, &len); 705c8c3fc56SRobert Watson 706c8c3fc56SRobert Watson sconnect = my_socket(PF_INET, SOCK_STREAM, 0); 707c8c3fc56SRobert Watson setnonblock(sconnect); 708c8c3fc56SRobert Watson my_connect(sconnect, (struct sockaddr *)&sin, len); 709c8c3fc56SRobert Watson 710c8c3fc56SRobert Watson sleep(1); 711c8c3fc56SRobert Watson sendfd(sv[0], slisten); 712c8c3fc56SRobert Watson close3(slisten, sv[0], sv[1]); 713c8c3fc56SRobert Watson sleep(1); 714c8c3fc56SRobert Watson close(sconnect); 715c8c3fc56SRobert Watson 716c8c3fc56SRobert Watson test_sysctls(inflight, openfiles); 717c8c3fc56SRobert Watson } 718c8c3fc56SRobert Watson 719*b0103260SKonstantin Belousov static void 720*b0103260SKonstantin Belousov recursion(void) 721*b0103260SKonstantin Belousov { 722*b0103260SKonstantin Belousov int fd[2], ff[2]; 723*b0103260SKonstantin Belousov int inflight, openfiles, deferred, deferred1; 724*b0103260SKonstantin Belousov 725*b0103260SKonstantin Belousov test = "recursion"; 726*b0103260SKonstantin Belousov printf("%s\n", test); 727*b0103260SKonstantin Belousov save_sysctls(&inflight, &openfiles); 728*b0103260SKonstantin Belousov deferred = getdeferred(); 729*b0103260SKonstantin Belousov 730*b0103260SKonstantin Belousov my_socketpair(fd); 731*b0103260SKonstantin Belousov 732*b0103260SKonstantin Belousov for (;;) { 733*b0103260SKonstantin Belousov if (socketpair(PF_UNIX, SOCK_STREAM, 0, ff) == -1) { 734*b0103260SKonstantin Belousov if (errno == EMFILE || errno == ENFILE) 735*b0103260SKonstantin Belousov break; 736*b0103260SKonstantin Belousov err(-1, "socketpair"); 737*b0103260SKonstantin Belousov } 738*b0103260SKonstantin Belousov sendfd(ff[0], fd[0]); 739*b0103260SKonstantin Belousov sendfd(ff[0], fd[1]); 740*b0103260SKonstantin Belousov close2(fd[1], fd[0]); 741*b0103260SKonstantin Belousov fd[0] = ff[0]; 742*b0103260SKonstantin Belousov fd[1] = ff[1]; 743*b0103260SKonstantin Belousov } 744*b0103260SKonstantin Belousov close2(fd[0], fd[1]); 745*b0103260SKonstantin Belousov sleep(1); 746*b0103260SKonstantin Belousov test_sysctls(inflight, openfiles); 747*b0103260SKonstantin Belousov deferred1 = getdeferred(); 748*b0103260SKonstantin Belousov if (deferred != deferred1) 749*b0103260SKonstantin Belousov errx(-1, "recursion: deferred before %d after %d", deferred, 750*b0103260SKonstantin Belousov deferred1); 751*b0103260SKonstantin Belousov } 752*b0103260SKonstantin Belousov 753c8c3fc56SRobert Watson #define RMDIR "rm -Rf " 754c8c3fc56SRobert Watson int 755c8c3fc56SRobert Watson main(int argc, char *argv[]) 756c8c3fc56SRobert Watson { 757c8c3fc56SRobert Watson char cmd[sizeof(RMDIR) + PATH_MAX]; 758c8c3fc56SRobert Watson int serrno; 759c8c3fc56SRobert Watson pid_t pid; 760c8c3fc56SRobert Watson 761c8c3fc56SRobert Watson strlcpy(dpath, "/tmp/unpgc.XXXXXXXX", sizeof(dpath)); 762c8c3fc56SRobert Watson if (mkdtemp(dpath) == NULL) 763c8c3fc56SRobert Watson err(-1, "mkdtemp"); 764c8c3fc56SRobert Watson 765c8c3fc56SRobert Watson /* 766c8c3fc56SRobert Watson * Set up a parent process to GC temporary storage when we're done. 767c8c3fc56SRobert Watson */ 768c8c3fc56SRobert Watson pid = fork(); 769c8c3fc56SRobert Watson if (pid < 0) { 770c8c3fc56SRobert Watson serrno = errno; 771c8c3fc56SRobert Watson (void)rmdir(dpath); 772c8c3fc56SRobert Watson errno = serrno; 773c8c3fc56SRobert Watson err(-1, "fork"); 774c8c3fc56SRobert Watson } 775c8c3fc56SRobert Watson if (pid > 0) { 776c8c3fc56SRobert Watson signal(SIGINT, SIG_IGN); 777c8c3fc56SRobert Watson while (waitpid(pid, NULL, 0) != pid); 778c8c3fc56SRobert Watson snprintf(cmd, sizeof(cmd), "%s %s", RMDIR, dpath); 779c8c3fc56SRobert Watson (void)system(cmd); 780c8c3fc56SRobert Watson exit(0); 781c8c3fc56SRobert Watson } 782c8c3fc56SRobert Watson 783c8c3fc56SRobert Watson printf("Start: inflight %d open %d\n", getinflight(), 784c8c3fc56SRobert Watson getopenfiles()); 785c8c3fc56SRobert Watson 786c8c3fc56SRobert Watson twosome_nothing(); 787c8c3fc56SRobert Watson twosome_drop(); 788c8c3fc56SRobert Watson 789c8c3fc56SRobert Watson threesome_nothing(); 790c8c3fc56SRobert Watson threesome_drop(); 791c8c3fc56SRobert Watson 792c8c3fc56SRobert Watson fivesome_nothing(); 793c8c3fc56SRobert Watson fivesome_drop(); 794c8c3fc56SRobert Watson 795c8c3fc56SRobert Watson complex_cycles(); 796c8c3fc56SRobert Watson 797c8c3fc56SRobert Watson listen_nothing(); 798c8c3fc56SRobert Watson listen_drop(); 799c8c3fc56SRobert Watson 800c8c3fc56SRobert Watson listen_connect_nothing(); 801c8c3fc56SRobert Watson listen_connect_drop(); 802c8c3fc56SRobert Watson 803*b0103260SKonstantin Belousov recursion(); 804*b0103260SKonstantin Belousov 805c8c3fc56SRobert Watson printf("Finish: inflight %d open %d\n", getinflight(), 806c8c3fc56SRobert Watson getopenfiles()); 807c8c3fc56SRobert Watson return (0); 808c8c3fc56SRobert Watson } 809