]> granicus.if.org Git - strace/commitdiff
tests: check tracing of orphaned process group
authorDmitry V. Levin <ldv@altlinux.org>
Wed, 6 Mar 2019 16:02:38 +0000 (16:02 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Wed, 6 Mar 2019 16:02:38 +0000 (16:02 +0000)
* tests/orphaned_process_group.c: New file.
* tests/.gitignore: Add orphaned_process_group.
* tests/Makefile.am (check_PROGRAMS): Likewise.
* tests/gen_tests.in (orphaned_process_group): New test.

tests/.gitignore
tests/Makefile.am
tests/gen_tests.in
tests/orphaned_process_group.c [new file with mode: 0644]

index 781e50a2d2e37708540a453b53045cabb398eb86..b481a82f39b8c181f20e5af07cf31610d2bdef44 100644 (file)
@@ -359,6 +359,7 @@ oldselect-efault-P
 oldstat
 open
 openat
+orphaned_process_group
 osf_utimes
 pause
 pc
index 5c52c8d6c46833a7f91c321a3d96d3c11e71f4f0..667a4bddc520b0d9e24010c58200b38cf663cf5d 100644 (file)
@@ -122,6 +122,7 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \
        nsyscalls-d \
        oldselect-P \
        oldselect-efault-P \
+       orphaned_process_group \
        pc \
        perf_event_open_nonverbose \
        perf_event_open_unabbrev \
index 128f4ca8dba5256d79125ad5bac964322ecbac97..f82b041022e8ba0b114b18820c82de2551a2e581 100644 (file)
@@ -307,6 +307,7 @@ oldselect-efault-P  -a13 -e trace=select -P /dev/full 9>>/dev/full
 oldstat        -a32 -v -P stat.sample -P /dev/full
 open   -a30 -P $NAME.sample
 openat -a36 -P $NAME.sample
+orphaned_process_group . "${srcdir=.}/PTRACE_SEIZE.sh"; run_strace_match_diff -f -e trace=none -e signal='!chld'
 osf_utimes     -a21
 pause  -a8 -esignal=none
 perf_event_open        -a1
diff --git a/tests/orphaned_process_group.c b/tests/orphaned_process_group.c
new file mode 100644 (file)
index 0000000..83ab6e3
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * Check tracing of orphaned process group.
+ *
+ * Copyright (c) 2019 The strace developers.
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "tests.h"
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+#define TIMEOUT 5
+
+static void
+alarm_handler(const int no)
+{
+       error_msg_and_skip("Orphaned process group semantics"
+                          " is not supported by the kernel");
+}
+
+int
+main(void)
+{
+       int status;
+
+       /*
+        * Unblock all signals.
+        */
+       static sigset_t mask;
+       if (sigprocmask(SIG_SETMASK, &mask, NULL))
+               perror_msg_and_fail("sigprocmask");
+
+       /*
+        * Create a pipe to track termination of processes.
+        */
+       int pipe_fds[2];
+       if (pipe(pipe_fds))
+               perror_msg_and_fail("pipe");
+
+       /*
+        * Create a leader for its own new process group.
+        */
+       pid_t leader = fork();
+       if (leader < 0)
+               perror_msg_and_fail("fork");
+
+       if (leader) {
+               /*
+                * Close the writing end of the pipe.
+                */
+               close(pipe_fds[1]);
+
+               /*
+                * Install the SIGALRM signal handler.
+                */
+               static const struct sigaction sa = {
+                       .sa_handler = alarm_handler
+               };
+               if (sigaction(SIGALRM, &sa, NULL))
+                       perror_msg_and_fail("sigaction");
+
+               /*
+                * Set an alarm clock.
+                */
+               alarm(TIMEOUT);
+
+               /*
+                * Wait for termination of the child process.
+                */
+               if (waitpid(leader, &status, 0) != leader)
+                       perror_msg_and_fail("waitpid leader");
+               if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
+                       error_msg_and_fail("waitpid leader: "
+                                          "unexpected wait status %d",
+                                          status);
+
+               /*
+                * Wait for termination of all processes
+                * in the process group of the child process.
+                */
+               if (read(pipe_fds[0], &status, sizeof(status)) != 0)
+                       perror_msg_and_fail("read");
+
+               /*
+                * At this point all processes are gone.
+                * Let the tracer time to catch up.
+                */
+               alarm(0);
+               sleep(1);
+               return 0;
+       }
+
+       /*
+        * Close the reading end of the pipe.
+        */
+       close(pipe_fds[0]);
+
+       /*
+        * Create a new process group.
+        */
+       if (setpgid(0, 0))
+               perror_msg_and_fail("setpgid");
+
+       /*
+        * When the leader process terminates, the process group becomes orphaned.
+        * If any member of the orphaned process group is stopped, then
+        * a SIGHUP signal followed by a SIGCONT signal is sent to each process
+        * in the orphaned process group.
+        * Create a process in a stopped state to activate this behaviour.
+        */
+       const pid_t stopped = fork();
+       if (stopped < 0)
+               perror_msg_and_fail("fork");
+       if (!stopped) {
+               static const struct sigaction sa = { .sa_handler = SIG_DFL };
+               if (sigaction(SIGHUP, &sa, NULL))
+                       perror_msg_and_fail("sigaction");
+
+               raise(SIGSTOP);
+               _exit(0);
+       }
+
+       /*
+        * Wait for the process to stop.
+        */
+       if (waitpid(stopped, &status, WUNTRACED) != stopped)
+               perror_msg_and_fail("waitpid WUNTRACED");
+       if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP)
+                error_msg_and_fail("unexpected wait status %d", status);
+
+       /*
+        * Print the expected output.
+        */
+       leader = getpid();
+       printf("%-5d --- %s {si_signo=%s, si_code=SI_TKILL"
+              ", si_pid=%d, si_uid=%u} ---\n",
+              stopped, "SIGSTOP", "SIGSTOP", stopped, geteuid());
+       printf("%-5d --- stopped by SIGSTOP ---\n", stopped);
+       printf("%-5d +++ exited with 0 +++\n", leader);
+       printf("%-5d --- %s {si_signo=%s, si_code=SI_KERNEL} ---\n",
+              stopped, "SIGHUP", "SIGHUP");
+       printf("%-5d +++ killed by %s +++\n", stopped, "SIGHUP");
+       printf("%-5d +++ exited with 0 +++\n", getppid());
+
+       /*
+        * Make the process group orphaned.
+        */
+       return 0;
+}