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