Module Name: src Committed By: pooka Date: Tue Mar 8 12:40:26 UTC 2011
Modified Files: src/tests/lib/librumpclient: Makefile t_exec.sh Added Files: src/tests/lib/librumpclient: h_execthr.c Log Message: add test case for multithreaded client calling exec To generate a diff of this commit: cvs rdiff -u -r1.3 -r1.4 src/tests/lib/librumpclient/Makefile cvs rdiff -u -r0 -r1.1 src/tests/lib/librumpclient/h_execthr.c cvs rdiff -u -r1.7 -r1.8 src/tests/lib/librumpclient/t_exec.sh Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/tests/lib/librumpclient/Makefile diff -u src/tests/lib/librumpclient/Makefile:1.3 src/tests/lib/librumpclient/Makefile:1.4 --- src/tests/lib/librumpclient/Makefile:1.3 Wed Feb 16 16:02:52 2011 +++ src/tests/lib/librumpclient/Makefile Tue Mar 8 12:40:25 2011 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.3 2011/02/16 16:02:52 pooka Exp $ +# $NetBSD: Makefile,v 1.4 2011/03/08 12:40:25 pooka Exp $ # .include <bsd.own.mk> @@ -7,11 +7,13 @@ TESTS_C= t_fd TESTS_C+= h_exec +TESTS_C+= h_execthr TESTS_SH= t_exec ATFFILE= yes LDADD+= -lrumpclient +LDADD.h_execthr= -lpthread .include <bsd.test.mk> Index: src/tests/lib/librumpclient/t_exec.sh diff -u src/tests/lib/librumpclient/t_exec.sh:1.7 src/tests/lib/librumpclient/t_exec.sh:1.8 --- src/tests/lib/librumpclient/t_exec.sh:1.7 Sat Feb 19 09:59:12 2011 +++ src/tests/lib/librumpclient/t_exec.sh Tue Mar 8 12:40:25 2011 @@ -1,4 +1,4 @@ -# $NetBSD: t_exec.sh,v 1.7 2011/02/19 09:59:12 pooka Exp $ +# $NetBSD: t_exec.sh,v 1.8 2011/03/08 12:40:25 pooka Exp $ # # Copyright (c) 2011 The NetBSD Foundation, Inc. # All rights reserved. @@ -127,6 +127,22 @@ rump.halt } +atf_test_case threxec cleanup +threxec_head() +{ + atf_set "descr" "check that threads are killed before exec continues" +} + +threxec_body() +{ + atf_check -s exit:0 rump_server ${RUMP_SERVER} + atf_check -s exit:0 $(atf_get_srcdir)/h_execthr +} + +threxec_cleanup() +{ + rump.halt +} atf_init_test_cases() { @@ -134,4 +150,5 @@ atf_add_test_case exec atf_add_test_case cloexec atf_add_test_case vfork + atf_add_test_case threxec } Added files: Index: src/tests/lib/librumpclient/h_execthr.c diff -u /dev/null src/tests/lib/librumpclient/h_execthr.c:1.1 --- /dev/null Tue Mar 8 12:40:26 2011 +++ src/tests/lib/librumpclient/h_execthr.c Tue Mar 8 12:40:25 2011 @@ -0,0 +1,184 @@ +/* $NetBSD: h_execthr.c,v 1.1 2011/03/08 12:40:25 pooka Exp $ */ + +/* + * Copyright (c) 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/types.h> +#include <sys/sysctl.h> + +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <rump/rumpclient.h> +#include <rump/rump_syscalls.h> + +static int canreturn = 0; + +/* + * Use a fairly large number of threads so that we have + * a better chance catching races. XXX: this is rumpuser's + * MAXWORKER-1. + */ +#define NTHR 63 + +static void * +wrk(void *arg) +{ + int fd = (uintptr_t)arg; + + rump_sys_read(fd, &fd, sizeof(fd)); + if (!canreturn) + errx(1, "should not have returned"); + if (fd != 37) + errx(1, "got invalid magic"); + + return NULL; +} + +static int +getproc(pid_t mypid, struct kinfo_proc2 *p) +{ + int name[6]; + size_t len = sizeof(*p); + + name[0] = CTL_KERN; + name[1] = KERN_PROC2; + name[2] = KERN_PROC_PID; + name[3] = mypid; + name[4] = len; + name[5] = 1; + + return rump_sys___sysctl(name, __arraycount(name), p, &len, NULL, 0); +} + +int +main(int argc, char *argv[], char *envp[]) +{ + struct kinfo_proc2 p; + char *execarg[3]; + int p1[2], p2[2]; + pid_t mypid; + pthread_t pt; + ssize_t n; + int i, execd; + char nexec[16]; + + if (argc > 1) + execd = atoi(argv[1]); + else + execd = 0; + sprintf(nexec, "%d", execd+1); + + if (rumpclient_init() == -1) { + if (execd) + err(1, "init execd"); + else + err(1, "init"); + } + mypid = rump_sys_getpid(); + + if (execd) { + canreturn = 1; + if (pthread_create(&pt, NULL, + wrk, (void *)(uintptr_t)2) != 0) + errx(1, "exec pthread_create"); + + i = 37; + rump_sys_write(3, &i, sizeof(i)); + pthread_join(pt, NULL); + + n = rump_sys_read(0, &i, sizeof(i)); + if (n != -1 || errno != EBADF) + errx(1, "post-exec cloexec works"); + + getproc(mypid, &p); + if (p.p_nlwps != 2) + errx(1, "invalid nlwps: %lld", (long long)p.p_nlwps); + + /* we passed? */ + if (execd > 10) + exit(0); + + rump_sys_close(2); + rump_sys_close(3); + } + + if (rump_sys_pipe(p1) == -1) + err(1, "pipe1"); + if (p1[0] != 0 || p1[1] != 1) + errx(1, "p1 assumptions failed %d %d", p1[0], p1[1]); + if (rump_sys_pipe(p2) == -1) + err(1, "pipe1"); + if (p2[0] != 2 || p2[1] != 3) + errx(1, "p2 assumptions failed"); + if (rump_sys_fcntl(p1[0], F_SETFD, FD_CLOEXEC) == -1) + err(1, "cloexec"); + if (rump_sys_fcntl(p1[1], F_SETFD, FD_CLOEXEC) == -1) + err(1, "cloexec"); + + for (i = 0; i < NTHR; i++) + if (pthread_create(&pt, NULL, + wrk, (void *)(uintptr_t)p1[0]) != 0) + errx(1, "pthread_create 1 %d", i); + + for (i = 0; i < NTHR; i++) + if (pthread_create(&pt, NULL, + wrk, (void *)(uintptr_t)p2[0]) != 0) + errx(1, "pthread_create 2 %d", i); + + /* wait for all the threads to be enjoying themselves */ + for (;;) { + getproc(mypid, &p); + if (p.p_nlwps == 2*NTHR + 2) + break; + usleep(10000); + } + +#ifdef notyet + /* + * load up one more (big) set. these won't start executing, though, + * but we're interested in if they create blockage + */ + for (i = 0; i < 3*NTHR; i++) + if (pthread_create(&pt, NULL, + wrk, (void *)(uintptr_t)p1[0]) != 0) + errx(1, "pthread_create 1 %d", i); +#endif + + /* then, we exec! */ + execarg[0] = argv[0]; + execarg[1] = nexec; + execarg[2] = NULL; + if (rumpclient_exec(argv[0], execarg, envp) == -1) + err(1, "exec"); +}