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