Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src Add new ATF tests: t_fork and t_vfork
details: https://anonhg.NetBSD.org/src/rev/23f7c77afb1c
branches: trunk
changeset: 319128:23f7c77afb1c
user: kamil <kamil%NetBSD.org@localhost>
date: Fri May 18 06:39:58 2018 +0000
description:
Add new ATF tests: t_fork and t_vfork
Test behavior of raise(signal) in either fork(2)ed or vfork(2)ed child.
Tests:
- raise1 SIGKILL
- raise2 SIGSTOP
- raise3 SIGTSTP
- raise4 SIGTTIN
- raise5 SIGTTOU
- raise6 SIGABRT
- raise7 SIGHUP
- raise8 SIGCONT
t_vfork:raise2 fails ignoring non-maskable SIGSTOP.
The remaining ones pass.
Sponsored by <The NetBSD Foundation>
diffstat:
distrib/sets/lists/debug/mi | 4 +-
distrib/sets/lists/tests/mi | 4 +-
tests/lib/libc/sys/Makefile | 4 +-
tests/lib/libc/sys/t_fork.c | 281 +++++++++++++++++++++++++++++++++++++++++++
tests/lib/libc/sys/t_vfork.c | 30 ++++
5 files changed, 320 insertions(+), 3 deletions(-)
diffs (truncated from 394 to 300 lines):
diff -r 5ff637dbdf38 -r 23f7c77afb1c distrib/sets/lists/debug/mi
--- a/distrib/sets/lists/debug/mi Fri May 18 05:51:23 2018 +0000
+++ b/distrib/sets/lists/debug/mi Fri May 18 06:39:58 2018 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.247 2018/05/04 12:44:40 sevan Exp $
+# $NetBSD: mi,v 1.248 2018/05/18 06:39:58 kamil Exp $
./etc/mtree/set.debug comp-sys-root
./usr/lib comp-sys-usr compatdir
./usr/lib/i18n/libBIG5_g.a comp-c-debuglib debuglib,compatfile
@@ -2073,6 +2073,7 @@
./usr/libdata/debug/usr/tests/lib/libc/sys/t_connect.debug tests-lib-debug debug,atf,compattestfile
./usr/libdata/debug/usr/tests/lib/libc/sys/t_context.debug tests-obsolete obsolete,compattestfile
./usr/libdata/debug/usr/tests/lib/libc/sys/t_dup.debug tests-lib-debug debug,atf,compattestfile
+./usr/libdata/debug/usr/tests/lib/libc/sys/t_fork.debug tests-lib-debug debug,atf,compattestfile
./usr/libdata/debug/usr/tests/lib/libc/sys/t_fsync.debug tests-lib-debug debug,atf,compattestfile
./usr/libdata/debug/usr/tests/lib/libc/sys/t_getcontext.debug tests-lib-debug debug,atf,compattestfile
./usr/libdata/debug/usr/tests/lib/libc/sys/t_getgroups.debug tests-lib-debug debug,atf,compattestfile
@@ -2133,6 +2134,7 @@
./usr/libdata/debug/usr/tests/lib/libc/sys/t_ucontext.debug tests-lib-debug debug,atf,compattestfile
./usr/libdata/debug/usr/tests/lib/libc/sys/t_umask.debug tests-lib-debug debug,atf,compattestfile
./usr/libdata/debug/usr/tests/lib/libc/sys/t_unlink.debug tests-lib-debug debug,atf,compattestfile
+./usr/libdata/debug/usr/tests/lib/libc/sys/t_vfork.debug tests-lib-debug debug,atf,compattestfile
./usr/libdata/debug/usr/tests/lib/libc/sys/t_wait.debug tests-lib-debug debug,atf,compattestfile
./usr/libdata/debug/usr/tests/lib/libc/sys/t_wait_noproc.debug tests-lib-debug debug,atf,compattestfile
./usr/libdata/debug/usr/tests/lib/libc/sys/t_wait_noproc_wnohang.debug tests-lib-debug debug,atf,compattestfile
diff -r 5ff637dbdf38 -r 23f7c77afb1c distrib/sets/lists/tests/mi
--- a/distrib/sets/lists/tests/mi Fri May 18 05:51:23 2018 +0000
+++ b/distrib/sets/lists/tests/mi Fri May 18 06:39:58 2018 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.782 2018/05/02 18:46:05 kamil Exp $
+# $NetBSD: mi,v 1.783 2018/05/18 06:39:59 kamil Exp $
#
# Note: don't delete entries from here - mark them as "obsolete" instead.
#
@@ -2757,6 +2757,7 @@
./usr/tests/lib/libc/sys/t_connect tests-lib-tests compattestfile,atf
./usr/tests/lib/libc/sys/t_context tests-obsolete obsolete
./usr/tests/lib/libc/sys/t_dup tests-lib-tests compattestfile,atf
+./usr/tests/lib/libc/sys/t_fork tests-lib-tests compattestfile,atf
./usr/tests/lib/libc/sys/t_fsync tests-lib-tests compattestfile,atf
./usr/tests/lib/libc/sys/t_getcontext tests-lib-tests compattestfile,atf
./usr/tests/lib/libc/sys/t_getgroups tests-lib-tests compattestfile,atf
@@ -2817,6 +2818,7 @@
./usr/tests/lib/libc/sys/t_ucontext tests-lib-tests compattestfile,atf
./usr/tests/lib/libc/sys/t_umask tests-lib-tests compattestfile,atf
./usr/tests/lib/libc/sys/t_unlink tests-lib-tests compattestfile,atf
+./usr/tests/lib/libc/sys/t_vfork tests-lib-tests compattestfile,atf
./usr/tests/lib/libc/sys/t_wait tests-lib-tests compattestfile,atf
./usr/tests/lib/libc/sys/t_wait_noproc tests-lib-tests compattestfile,atf
./usr/tests/lib/libc/sys/t_wait_noproc_wnohang tests-lib-tests compattestfile,atf
diff -r 5ff637dbdf38 -r 23f7c77afb1c tests/lib/libc/sys/Makefile
--- a/tests/lib/libc/sys/Makefile Fri May 18 05:51:23 2018 +0000
+++ b/tests/lib/libc/sys/Makefile Fri May 18 06:39:58 2018 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.50 2018/02/25 14:27:07 kamil Exp $
+# $NetBSD: Makefile,v 1.51 2018/05/18 06:39:58 kamil Exp $
MKMAN= no
@@ -16,6 +16,7 @@
TESTS_C+= t_clone
TESTS_C+= t_connect
TESTS_C+= t_dup
+TESTS_C+= t_fork
TESTS_C+= t_fsync
TESTS_C+= t_getcontext
TESTS_C+= t_getgroups
@@ -74,6 +75,7 @@
TESTS_C+= t_ucontext
TESTS_C+= t_umask
TESTS_C+= t_unlink
+TESTS_C+= t_vfork
TESTS_C+= t_wait
TESTS_C+= t_wait_noproc
TESTS_C+= t_wait_noproc_wnohang
diff -r 5ff637dbdf38 -r 23f7c77afb1c tests/lib/libc/sys/t_fork.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/lib/libc/sys/t_fork.c Fri May 18 06:39:58 2018 +0000
@@ -0,0 +1,281 @@
+/* $NetBSD: t_fork.c,v 1.1 2018/05/18 06:39:58 kamil Exp $ */
+
+/*-
+ * Copyright (c) 2018 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/cdefs.h>
+__COPYRIGHT("@(#) Copyright (c) 2018\
+ The NetBSD Foundation, inc. All rights reserved.");
+__RCSID("$NetBSD: t_fork.c,v 1.1 2018/05/18 06:39:58 kamil Exp $");
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <err.h>
+#include <errno.h>
+
+#include <atf-c.h>
+
+#ifdef VFORK
+#define FORK vfork
+#else
+#define FORK fork
+#endif
+
+/*
+ * A child process cannot call atf functions and expect them to magically
+ * work like in the parent.
+ * The printf(3) messaging from a child will not work out of the box as well
+ * without estabilishing a communication protocol with its parent. To not
+ * overcomplicate the tests - do not log from a child and use err(3)/errx(3)
+ * wrapped with ASSERT_EQ()/ASSERT_NEQ() as that is guaranteed to work.
+ */
+#define ASSERT_EQ(x, y) \
+do { \
+ uintmax_t vx = (x); \
+ uintmax_t vy = (y); \
+ int ret = vx == vy; \
+ if (!ret) \
+ errx(EXIT_FAILURE, "%s:%d %s(): Assertion failed for: " \
+ "%s(%ju) == %s(%ju)", __FILE__, __LINE__, __func__, \
+ #x, vx, #y, vy); \
+} while (/*CONSTCOND*/0)
+
+#define ASSERT_NEQ(x, y) \
+do { \
+ uintmax_t vx = (x); \
+ uintmax_t vy = (y); \
+ int ret = vx != vy; \
+ if (!ret) \
+ errx(EXIT_FAILURE, "%s:%d %s(): Assertion failed for: " \
+ "%s(%ju) != %s(%ju)", __FILE__, __LINE__, __func__, \
+ #x, vx, #y, vy); \
+} while (/*CONSTCOND*/0)
+
+static pid_t
+await_stopped_child(pid_t process)
+{
+ struct kinfo_proc2 *p = NULL;
+ size_t i, len;
+ pid_t child = -1;
+
+ int name[] = {
+ [0] = CTL_KERN,
+ [1] = KERN_PROC2,
+ [2] = KERN_PROC_ALL,
+ [3] = 0,
+ [4] = sizeof(struct kinfo_proc2),
+ [5] = 0
+ };
+
+ const size_t namelen = __arraycount(name);
+
+ /* Await the process becoming a zombie */
+ while(1) {
+ name[5] = 0;
+
+ ASSERT_EQ(sysctl(name, namelen, 0, &len, NULL, 0), 0);
+
+ ASSERT_EQ(reallocarr(&p, len, sizeof(struct kinfo_proc2)), 0);
+
+ name[5] = len;
+
+ ASSERT_EQ(sysctl(name, namelen, p, &len, NULL, 0), 0);
+
+ for (i = 0; i < len/sizeof(struct kinfo_proc2); i++) {
+ if (p[i].p_pid == getpid())
+ continue;
+ if (p[i].p_ppid != process)
+ continue;
+ if (p[i].p_stat != LSSTOP)
+ continue;
+ child = p[i].p_pid;
+ break;
+ }
+
+ if (child != -1)
+ break;
+
+ ASSERT_EQ(usleep(1000), 0);
+ }
+
+ /* Free the buffer */
+ ASSERT_EQ(reallocarr(&p, 0, sizeof(struct kinfo_proc2)), 0);
+
+ return child;
+}
+
+static void
+raise_raw(int sig)
+{
+ int rv, status;
+ pid_t child, parent, watcher, wpid;
+ int expect_core = (sig == SIGABRT) ? 1 : 0;
+
+#ifdef VFORK
+ if (sig == SIGSTOP) {
+ atf_tc_expect_fail("SIGSTOP shall not be ignored");
+ }
+#endif
+
+ /*
+ * Spawn a dedicated thread to watch for a stopped child and emit
+ * the SIGTERM signal to it.
+ *
+ * This is required in vfork(2)ing parent and optional in fork(2).
+ *
+ * vfork(2) might clobber watcher, this means that it's safer and
+ * simpler to reparent this process to initproc and forget about it.
+ */
+ if (sig == SIGSTOP
+#ifndef VFORK
+ || (sig == SIGTSTP || sig == SIGTTIN || sig == SIGTTOU)
+#endif
+ ) {
+
+ parent = getpid();
+
+ watcher = fork();
+ ATF_REQUIRE(watcher != 1);
+ if (watcher == 0) {
+ /* Double fork(2) trick to reparent to initproc */
+ watcher = fork();
+ ASSERT_NEQ(watcher, -1);
+ if (watcher != 0)
+ _exit(0);
+
+ child = await_stopped_child(parent);
+
+ errno = 0;
+ rv = kill(child, SIGKILL);
+ ASSERT_EQ(rv, 0);
+ ASSERT_EQ(errno, 0);
+
+ /* This exit value will be collected by initproc */
+ _exit(0);
+ }
+
+ wpid = waitpid(watcher, &status, 0);
+
+ ATF_REQUIRE_EQ(wpid, watcher);
+
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE(!WIFCONTINUED(status));
+ ATF_REQUIRE(!WIFSIGNALED(status));
+ ATF_REQUIRE(!WIFSTOPPED(status));
+ ATF_REQUIRE_EQ(WEXITSTATUS(status), 0);
+ }
+
+ child = FORK();
+ ATF_REQUIRE(child != 1);
+ if (child == 0) {
+ rv = raise(sig);
+ ASSERT_EQ(rv, 0);
+ _exit(0);
+ }
+ wpid = waitpid(child, &status, 0);
+
+ ATF_REQUIRE_EQ(wpid, child);
+
+ switch (sig) {
+ case SIGKILL:
+ case SIGABRT:
+ case SIGHUP:
+ ATF_REQUIRE(!WIFEXITED(status));
+ ATF_REQUIRE(!WIFCONTINUED(status));
+ ATF_REQUIRE(WIFSIGNALED(status));
+ ATF_REQUIRE(!WIFSTOPPED(status));
+ ATF_REQUIRE_EQ(WTERMSIG(status), sig);
+ ATF_REQUIRE_EQ(!!WCOREDUMP(status), expect_core);
+ break;
+#ifdef VFORK
+ case SIGTSTP:
+ case SIGTTIN:
+ case SIGTTOU:
Home |
Main Index |
Thread Index |
Old Index