8a8cfb
commit 96cd0558bcd69481ccc42e1b392f0c0b36fce2b0
8a8cfb
Author: Florian Weimer <fweimer@redhat.com>
8a8cfb
Date:   Wed Nov 28 19:59:45 2018 +0100
8a8cfb
8a8cfb
    support: Add signal support to support_capture_subprocess_check
8a8cfb
    
8a8cfb
    Signal zero does not terminate a process, so it is safe to use negative
8a8cfb
    values for signal numbers.
8a8cfb
    
8a8cfb
    Adjust libio/tst-vtables-common.c to use this new functionality,
8a8cfb
    instead of determining the termination status for a signal indirectly.
8a8cfb
8a8cfb
diff --git a/libio/tst-vtables-common.c b/libio/tst-vtables-common.c
8a8cfb
index 5e3101206919fa1b..85e246cd1131f8e8 100644
8a8cfb
--- a/libio/tst-vtables-common.c
8a8cfb
+++ b/libio/tst-vtables-common.c
8a8cfb
@@ -380,21 +380,6 @@ without_compatibility_fflush (void *closure)
8a8cfb
   _exit (1);
8a8cfb
 }
8a8cfb
 
8a8cfb
-/* Exit status after abnormal termination.  */
8a8cfb
-static int termination_status;
8a8cfb
-
8a8cfb
-static void
8a8cfb
-init_termination_status (void)
8a8cfb
-{
8a8cfb
-  pid_t pid = xfork ();
8a8cfb
-  if (pid == 0)
8a8cfb
-    abort ();
8a8cfb
-  xwaitpid (pid, &termination_status, 0);
8a8cfb
-
8a8cfb
-  TEST_VERIFY (WIFSIGNALED (termination_status));
8a8cfb
-  TEST_COMPARE (WTERMSIG (termination_status), SIGABRT);
8a8cfb
-}
8a8cfb
-
8a8cfb
 static void
8a8cfb
 check_for_termination (const char *name, void (*callback) (void *))
8a8cfb
 {
8a8cfb
@@ -404,7 +389,7 @@ check_for_termination (const char *name, void (*callback) (void *))
8a8cfb
   shared->calls = 0;
8a8cfb
   struct support_capture_subprocess proc
8a8cfb
     = support_capture_subprocess (callback, NULL);
8a8cfb
-  support_capture_subprocess_check (&proc, name, termination_status,
8a8cfb
+  support_capture_subprocess_check (&proc, name, -SIGABRT,
8a8cfb
                                     sc_allow_stderr);
8a8cfb
   const char *message
8a8cfb
     = "Fatal error: glibc detected an invalid stdio handle\n";
8a8cfb
@@ -491,7 +476,6 @@ run_tests (bool initially_disabled)
8a8cfb
 
8a8cfb
   shared = support_shared_allocate (sizeof (*shared));
8a8cfb
   shared->initially_disabled = initially_disabled;
8a8cfb
-  init_termination_status ();
8a8cfb
 
8a8cfb
   if (initially_disabled)
8a8cfb
     {
8a8cfb
diff --git a/support/capture_subprocess.h b/support/capture_subprocess.h
8a8cfb
index d5eac84d09ae325f..2d2384e73df0d2d0 100644
8a8cfb
--- a/support/capture_subprocess.h
8a8cfb
+++ b/support/capture_subprocess.h
8a8cfb
@@ -55,13 +55,16 @@ enum support_capture_allow
8a8cfb
   sc_allow_stderr = 0x04,
8a8cfb
 };
8a8cfb
 
8a8cfb
-/* Check that the subprocess exited with STATUS and that only the
8a8cfb
-   allowed outputs happened.  ALLOWED is a combination of
8a8cfb
-   support_capture_allow flags.  Report errors under the CONTEXT
8a8cfb
-   message.  */
8a8cfb
+/* Check that the subprocess exited and that only the allowed outputs
8a8cfb
+   happened.  If STATUS_OR_SIGNAL is nonnegative, it is the expected
8a8cfb
+   (decoded) exit status of the process, as returned by WEXITSTATUS.
8a8cfb
+   If STATUS_OR_SIGNAL is negative, -STATUS_OR_SIGNAL is the expected
8a8cfb
+   termination signal, as returned by WTERMSIG.  ALLOWED is a
8a8cfb
+   combination of support_capture_allow flags.  Report errors under
8a8cfb
+   the CONTEXT message.  */
8a8cfb
 void support_capture_subprocess_check (struct support_capture_subprocess *,
8a8cfb
-                                       const char *context, int status,
8a8cfb
-                                       int allowed)
8a8cfb
+                                       const char *context,
8a8cfb
+                                       int status_or_signal, int allowed)
8a8cfb
   __attribute__ ((nonnull (1, 2)));
8a8cfb
 
8a8cfb
 #endif /* SUPPORT_CAPTURE_SUBPROCESS_H */
8a8cfb
diff --git a/support/support_capture_subprocess_check.c b/support/support_capture_subprocess_check.c
8a8cfb
index ff5ee89fb02599ae..8b4c352c96227b78 100644
8a8cfb
--- a/support/support_capture_subprocess_check.c
8a8cfb
+++ b/support/support_capture_subprocess_check.c
8a8cfb
@@ -20,6 +20,7 @@
8a8cfb
 #include <stdio.h>
8a8cfb
 #include <support/capture_subprocess.h>
8a8cfb
 #include <support/check.h>
8a8cfb
+#include <sys/wait.h>
8a8cfb
 
8a8cfb
 static void
8a8cfb
 print_context (const char *context, bool *failed)
8a8cfb
@@ -31,9 +32,22 @@ print_context (const char *context, bool *failed)
8a8cfb
   printf ("error: subprocess failed: %s\n", context);
8a8cfb
 }
8a8cfb
 
8a8cfb
+static void
8a8cfb
+print_actual_status (struct support_capture_subprocess *proc)
8a8cfb
+{
8a8cfb
+  if (WIFEXITED (proc->status))
8a8cfb
+    printf ("error:   actual exit status: %d [0x%x]\n",
8a8cfb
+            WEXITSTATUS (proc->status), proc->status);
8a8cfb
+  else if (WIFSIGNALED (proc->status))
8a8cfb
+    printf ("error:   actual termination signal: %d [0x%x]\n",
8a8cfb
+            WTERMSIG (proc->status), proc->status);
8a8cfb
+  else
8a8cfb
+    printf ("error:   actual undecoded exit status: [0x%x]\n", proc->status);
8a8cfb
+}
8a8cfb
+
8a8cfb
 void
8a8cfb
 support_capture_subprocess_check (struct support_capture_subprocess *proc,
8a8cfb
-                                  const char *context, int status,
8a8cfb
+                                  const char *context, int status_or_signal,
8a8cfb
                                   int allowed)
8a8cfb
 {
8a8cfb
   TEST_VERIFY ((allowed & sc_allow_none)
8a8cfb
@@ -44,11 +58,28 @@ support_capture_subprocess_check (struct support_capture_subprocess *proc,
8a8cfb
                      || (allowed & sc_allow_stderr))));
8a8cfb
 
8a8cfb
   bool failed = false;
8a8cfb
-  if (proc->status != status)
8a8cfb
+  if (status_or_signal >= 0)
8a8cfb
     {
8a8cfb
-      print_context (context, &failed);
8a8cfb
-      printf ("error:   expected exit status: %d\n", status);
8a8cfb
-      printf ("error:   actual exit status:   %d\n", proc->status);
8a8cfb
+      /* Expect regular termination.  */
8a8cfb
+      if (!(WIFEXITED (proc->status)
8a8cfb
+            && WEXITSTATUS (proc->status) == status_or_signal))
8a8cfb
+        {
8a8cfb
+          print_context (context, &failed);
8a8cfb
+          printf ("error:   expected exit status: %d\n", status_or_signal);
8a8cfb
+          print_actual_status (proc);
8a8cfb
+        }
8a8cfb
+    }
8a8cfb
+  else
8a8cfb
+    {
8a8cfb
+      /* status_or_signal < 0.  Expect termination by signal.  */
8a8cfb
+      if (!(WIFSIGNALED (proc->status)
8a8cfb
+            && WTERMSIG (proc->status) == -status_or_signal))
8a8cfb
+        {
8a8cfb
+          print_context (context, &failed);
8a8cfb
+          printf ("error:   expected termination signal: %d\n",
8a8cfb
+                  -status_or_signal);
8a8cfb
+          print_actual_status (proc);
8a8cfb
+        }
8a8cfb
     }
8a8cfb
   if (!(allowed & sc_allow_stdout) && proc->out.length != 0)
8a8cfb
     {
8a8cfb
diff --git a/support/tst-support_capture_subprocess.c b/support/tst-support_capture_subprocess.c
8a8cfb
index 63b6699622f97fcc..99570879eedd65b1 100644
8a8cfb
--- a/support/tst-support_capture_subprocess.c
8a8cfb
+++ b/support/tst-support_capture_subprocess.c
8a8cfb
@@ -285,15 +285,29 @@ do_multiple_tests (enum test_type type)
8a8cfb
 
8a8cfb
               check_stream ("stdout", &result.out, test.out);
8a8cfb
               check_stream ("stderr", &result.err, test.err);
8a8cfb
+
8a8cfb
+              /* Allowed output for support_capture_subprocess_check.  */
8a8cfb
+              int check_allow = 0;
8a8cfb
+              if (lengths[length_idx_stdout] > 0)
8a8cfb
+                check_allow |= sc_allow_stdout;
8a8cfb
+              if (lengths[length_idx_stderr] > 0)
8a8cfb
+                check_allow |= sc_allow_stderr;
8a8cfb
+              if (check_allow == 0)
8a8cfb
+                check_allow = sc_allow_none;
8a8cfb
+
8a8cfb
               if (test.signal != 0)
8a8cfb
                 {
8a8cfb
                   TEST_VERIFY (WIFSIGNALED (result.status));
8a8cfb
                   TEST_VERIFY (WTERMSIG (result.status) == test.signal);
8a8cfb
+                  support_capture_subprocess_check (&result, "signal",
8a8cfb
+                                                    -SIGTERM, check_allow);
8a8cfb
                 }
8a8cfb
               else
8a8cfb
                 {
8a8cfb
                   TEST_VERIFY (WIFEXITED (result.status));
8a8cfb
                   TEST_VERIFY (WEXITSTATUS (result.status) == test.status);
8a8cfb
+                  support_capture_subprocess_check (&result, "exit",
8a8cfb
+                                                    test.status, check_allow);
8a8cfb
                 }
8a8cfb
               support_capture_subprocess_free (&result);
8a8cfb
               free (test.out);