tst_run_cmd: Make the tst_run_cmd survive SIGCHLD
The tst_sig() installs poisoned signal handlers for all signals the test
is not expected to get, this causes abort in tst_run_cmd right after the
child exits and parent starts running.
This commit makes the tst_run_cmd temporarily disable the handler for
SIGCHLD (the handler is set to SIG_DFL at the start of the tst_run_cmd
function and restored at the end of it) so that we don't have to disable
the poisoned handler in each test using tst_run_cmd.
Signed-off-by: Cyril Hrubis <chrubis@suse.cz>
diff --git a/lib/tst_run_cmd.c b/lib/tst_run_cmd.c
index 804103c..4eb32e6 100644
--- a/lib/tst_run_cmd.c
+++ b/lib/tst_run_cmd.c
@@ -25,6 +25,7 @@
#include <sys/wait.h>
#include <fcntl.h>
#include <unistd.h>
+#include <signal.h>
#include "test.h"
#define OPEN_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
@@ -40,6 +41,16 @@
"argument list is empty at %s:%d", __FILE__, __LINE__);
}
+ /*
+ * The tst_sig() install poisoned signal handlers for all signals the
+ * test is not expected to get.
+ *
+ * So we temporarily disable the handler for sigchild we get after our
+ * child exits so that we don't have to disable it in each test that
+ * uses this interface.
+ */
+ void *old_handler = signal(SIGCHLD, SIG_DFL);
+
pid_t pid = vfork();
if (pid == -1) {
tst_brkm(TBROK | TERRNO, cleanup_fn, "vfork failed at %s:%d",
@@ -62,10 +73,12 @@
int ret = -1;
if (waitpid(pid, &ret, 0) != pid) {
- tst_brkm(TBROK, cleanup_fn, "waitpid failed at %s:%d",
+ tst_brkm(TBROK | TERRNO, cleanup_fn, "waitpid failed at %s:%d",
__FILE__, __LINE__);
}
+ signal(SIGCHLD, old_handler);
+
if (!WIFEXITED(ret) || WEXITSTATUS(ret) != 0) {
tst_brkm(TBROK, cleanup_fn, "failed to exec cmd '%s' at %s:%d",
argv[0], __FILE__, __LINE__);