1*57718be8SEnji Cooper /* $NetBSD: h_execthr.c,v 1.3 2014/08/13 00:03:00 pooka Exp $ */ 2*57718be8SEnji Cooper 3*57718be8SEnji Cooper /* 4*57718be8SEnji Cooper * Copyright (c) 2011 The NetBSD Foundation, Inc. 5*57718be8SEnji Cooper * All rights reserved. 6*57718be8SEnji Cooper * 7*57718be8SEnji Cooper * Redistribution and use in source and binary forms, with or without 8*57718be8SEnji Cooper * modification, are permitted provided that the following conditions 9*57718be8SEnji Cooper * are met: 10*57718be8SEnji Cooper * 1. Redistributions of source code must retain the above copyright 11*57718be8SEnji Cooper * notice, this list of conditions and the following disclaimer. 12*57718be8SEnji Cooper * 2. Redistributions in binary form must reproduce the above copyright 13*57718be8SEnji Cooper * notice, this list of conditions and the following disclaimer in the 14*57718be8SEnji Cooper * documentation and/or other materials provided with the distribution. 15*57718be8SEnji Cooper * 16*57718be8SEnji Cooper * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 17*57718be8SEnji Cooper * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 18*57718be8SEnji Cooper * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19*57718be8SEnji Cooper * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20*57718be8SEnji Cooper * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY 21*57718be8SEnji Cooper * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22*57718be8SEnji Cooper * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 23*57718be8SEnji Cooper * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24*57718be8SEnji Cooper * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25*57718be8SEnji Cooper * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 26*57718be8SEnji Cooper * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27*57718be8SEnji Cooper * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28*57718be8SEnji Cooper */ 29*57718be8SEnji Cooper 30*57718be8SEnji Cooper #include <sys/types.h> 31*57718be8SEnji Cooper #include <sys/sysctl.h> 32*57718be8SEnji Cooper 33*57718be8SEnji Cooper #include <err.h> 34*57718be8SEnji Cooper #include <errno.h> 35*57718be8SEnji Cooper #include <fcntl.h> 36*57718be8SEnji Cooper #include <pthread.h> 37*57718be8SEnji Cooper #include <stdio.h> 38*57718be8SEnji Cooper #include <stdlib.h> 39*57718be8SEnji Cooper #include <string.h> 40*57718be8SEnji Cooper #include <unistd.h> 41*57718be8SEnji Cooper 42*57718be8SEnji Cooper #include <rump/rumpclient.h> 43*57718be8SEnji Cooper #include <rump/rump_syscalls.h> 44*57718be8SEnji Cooper 45*57718be8SEnji Cooper static int canreturn = 0; 46*57718be8SEnji Cooper 47*57718be8SEnji Cooper /* 48*57718be8SEnji Cooper * Use a fairly large number of threads so that we have 49*57718be8SEnji Cooper * a better chance catching races. XXX: this is rumpuser's 50*57718be8SEnji Cooper * MAXWORKER-1. 51*57718be8SEnji Cooper */ 52*57718be8SEnji Cooper #define NTHR 63 53*57718be8SEnji Cooper 54*57718be8SEnji Cooper #define P1_0 3 55*57718be8SEnji Cooper #define P1_1 4 56*57718be8SEnji Cooper #define P2_0 5 57*57718be8SEnji Cooper #define P2_1 6 58*57718be8SEnji Cooper 59*57718be8SEnji Cooper static void * 60*57718be8SEnji Cooper wrk(void *arg) 61*57718be8SEnji Cooper { 62*57718be8SEnji Cooper int fd = (uintptr_t)arg; 63*57718be8SEnji Cooper 64*57718be8SEnji Cooper rump_sys_read(fd, &fd, sizeof(fd)); 65*57718be8SEnji Cooper if (!canreturn) 66*57718be8SEnji Cooper errx(1, "should not have returned"); 67*57718be8SEnji Cooper if (fd != 37) 68*57718be8SEnji Cooper errx(1, "got invalid magic"); 69*57718be8SEnji Cooper 70*57718be8SEnji Cooper return NULL; 71*57718be8SEnji Cooper } 72*57718be8SEnji Cooper 73*57718be8SEnji Cooper static int 74*57718be8SEnji Cooper getproc(pid_t mypid, struct kinfo_proc2 *p) 75*57718be8SEnji Cooper { 76*57718be8SEnji Cooper int name[6]; 77*57718be8SEnji Cooper size_t len = sizeof(*p); 78*57718be8SEnji Cooper 79*57718be8SEnji Cooper name[0] = CTL_KERN; 80*57718be8SEnji Cooper name[1] = KERN_PROC2; 81*57718be8SEnji Cooper name[2] = KERN_PROC_PID; 82*57718be8SEnji Cooper name[3] = mypid; 83*57718be8SEnji Cooper name[4] = len; 84*57718be8SEnji Cooper name[5] = 1; 85*57718be8SEnji Cooper 86*57718be8SEnji Cooper return rump_sys___sysctl(name, __arraycount(name), p, &len, NULL, 0); 87*57718be8SEnji Cooper } 88*57718be8SEnji Cooper 89*57718be8SEnji Cooper int 90*57718be8SEnji Cooper main(int argc, char *argv[], char *envp[]) 91*57718be8SEnji Cooper { 92*57718be8SEnji Cooper struct kinfo_proc2 p; 93*57718be8SEnji Cooper char *execarg[3]; 94*57718be8SEnji Cooper int p1[2], p2[2]; 95*57718be8SEnji Cooper pid_t mypid; 96*57718be8SEnji Cooper pthread_t pt; 97*57718be8SEnji Cooper ssize_t n; 98*57718be8SEnji Cooper int i, execd; 99*57718be8SEnji Cooper char nexec[16]; 100*57718be8SEnji Cooper 101*57718be8SEnji Cooper if (argc > 1) 102*57718be8SEnji Cooper execd = atoi(argv[1]); 103*57718be8SEnji Cooper else 104*57718be8SEnji Cooper execd = 0; 105*57718be8SEnji Cooper sprintf(nexec, "%d", execd+1); 106*57718be8SEnji Cooper 107*57718be8SEnji Cooper if (rumpclient_init() == -1) { 108*57718be8SEnji Cooper if (execd) 109*57718be8SEnji Cooper err(1, "init execd"); 110*57718be8SEnji Cooper else 111*57718be8SEnji Cooper err(1, "init"); 112*57718be8SEnji Cooper } 113*57718be8SEnji Cooper mypid = rump_sys_getpid(); 114*57718be8SEnji Cooper 115*57718be8SEnji Cooper if (execd) { 116*57718be8SEnji Cooper canreturn = 1; 117*57718be8SEnji Cooper if (pthread_create(&pt, NULL, 118*57718be8SEnji Cooper wrk, (void *)(uintptr_t)P2_0) != 0) 119*57718be8SEnji Cooper errx(1, "exec pthread_create"); 120*57718be8SEnji Cooper 121*57718be8SEnji Cooper i = 37; 122*57718be8SEnji Cooper rump_sys_write(P2_1, &i, sizeof(i)); 123*57718be8SEnji Cooper pthread_join(pt, NULL); 124*57718be8SEnji Cooper 125*57718be8SEnji Cooper n = rump_sys_read(P1_0, &i, sizeof(i)); 126*57718be8SEnji Cooper if (n != -1 || errno != EBADF) 127*57718be8SEnji Cooper errx(1, "post-exec cloexec works"); 128*57718be8SEnji Cooper 129*57718be8SEnji Cooper getproc(mypid, &p); 130*57718be8SEnji Cooper if (p.p_nlwps != 2) 131*57718be8SEnji Cooper errx(1, "invalid nlwps: %lld", (long long)p.p_nlwps); 132*57718be8SEnji Cooper 133*57718be8SEnji Cooper /* we passed? */ 134*57718be8SEnji Cooper if (execd > 10) 135*57718be8SEnji Cooper exit(0); 136*57718be8SEnji Cooper 137*57718be8SEnji Cooper rump_sys_close(P2_0); 138*57718be8SEnji Cooper rump_sys_close(P2_1); 139*57718be8SEnji Cooper } 140*57718be8SEnji Cooper 141*57718be8SEnji Cooper if (rump_sys_pipe(p1) == -1) 142*57718be8SEnji Cooper err(1, "pipe1"); 143*57718be8SEnji Cooper if (p1[0] != P1_0 || p1[1] != P1_1) 144*57718be8SEnji Cooper errx(1, "p1 assumptions failed %d %d", p1[0], p1[1]); 145*57718be8SEnji Cooper if (rump_sys_pipe(p2) == -1) 146*57718be8SEnji Cooper err(1, "pipe1"); 147*57718be8SEnji Cooper if (p2[0] != P2_0 || p2[1] != P2_1) 148*57718be8SEnji Cooper errx(1, "p2 assumptions failed"); 149*57718be8SEnji Cooper if (rump_sys_fcntl(p1[0], F_SETFD, FD_CLOEXEC) == -1) 150*57718be8SEnji Cooper err(1, "cloexec"); 151*57718be8SEnji Cooper if (rump_sys_fcntl(p1[1], F_SETFD, FD_CLOEXEC) == -1) 152*57718be8SEnji Cooper err(1, "cloexec"); 153*57718be8SEnji Cooper 154*57718be8SEnji Cooper for (i = 0; i < NTHR; i++) 155*57718be8SEnji Cooper if (pthread_create(&pt, NULL, 156*57718be8SEnji Cooper wrk, (void *)(uintptr_t)p1[0]) != 0) 157*57718be8SEnji Cooper errx(1, "pthread_create 1 %d", i); 158*57718be8SEnji Cooper 159*57718be8SEnji Cooper for (i = 0; i < NTHR; i++) 160*57718be8SEnji Cooper if (pthread_create(&pt, NULL, 161*57718be8SEnji Cooper wrk, (void *)(uintptr_t)p2[0]) != 0) 162*57718be8SEnji Cooper errx(1, "pthread_create 2 %d", i); 163*57718be8SEnji Cooper 164*57718be8SEnji Cooper /* wait for all the threads to be enjoying themselves */ 165*57718be8SEnji Cooper for (;;) { 166*57718be8SEnji Cooper getproc(mypid, &p); 167*57718be8SEnji Cooper if (p.p_nlwps == 2*NTHR + 2) 168*57718be8SEnji Cooper break; 169*57718be8SEnji Cooper usleep(10000); 170*57718be8SEnji Cooper } 171*57718be8SEnji Cooper 172*57718be8SEnji Cooper /* 173*57718be8SEnji Cooper * load up one more (big) set. these won't start executing, though, 174*57718be8SEnji Cooper * but we're interested in if they create blockage 175*57718be8SEnji Cooper */ 176*57718be8SEnji Cooper for (i = 0; i < 3*NTHR; i++) 177*57718be8SEnji Cooper if (pthread_create(&pt, NULL, 178*57718be8SEnji Cooper wrk, (void *)(uintptr_t)p1[0]) != 0) 179*57718be8SEnji Cooper errx(1, "pthread_create 1 %d", i); 180*57718be8SEnji Cooper 181*57718be8SEnji Cooper /* then, we exec! */ 182*57718be8SEnji Cooper execarg[0] = argv[0]; 183*57718be8SEnji Cooper execarg[1] = nexec; 184*57718be8SEnji Cooper execarg[2] = NULL; 185*57718be8SEnji Cooper if (rumpclient_exec(argv[0], execarg, envp) == -1) 186*57718be8SEnji Cooper err(1, "exec"); 187*57718be8SEnji Cooper } 188