diff options
author | Peter Hutterer <peter.hutterer@who-t.net> | 2012-08-15 09:30:15 +1000 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2012-08-17 10:19:41 +1000 |
commit | 8653076163c6c515f77cb3a7e4b0bc8dd416537f (patch) | |
tree | 9b16f6d41cf34ea24cc60c7f9b1f73aa7f9f057a | |
parent | 9263c0fc5be087c5876700dd53be710f39f2f317 (diff) |
process: terminate the child if the parent dies
It's annoying to have the forked X server linger around when the test
segfaults, so make sure we take it down with us.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Chase Douglas <chase.douglas@canonical.com>
-rw-r--r-- | src/process.cpp | 5 | ||||
-rw-r--r-- | test/process-test.cpp | 45 |
2 files changed, 50 insertions, 0 deletions
diff --git a/src/process.cpp b/src/process.cpp index ec39c97..1a1739a 100644 --- a/src/process.cpp +++ b/src/process.cpp @@ -27,6 +27,7 @@ #include "xorg/gtest/xorg-gtest-process.h" +#include <sys/prctl.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> @@ -81,6 +82,10 @@ void xorg::testing::Process::Start(const std::string &program, const std::vector close(2); } +#ifdef __linux + prctl(PR_SET_PDEATHSIG, SIGTERM); +#endif + std::vector<char*> args; std::vector<std::string>::const_iterator it; diff --git a/test/process-test.cpp b/test/process-test.cpp index dc5402c..183b9f8 100644 --- a/test/process-test.cpp +++ b/test/process-test.cpp @@ -1,3 +1,5 @@ +#include <errno.h> +#include <unistd.h> #include <sys/types.h> #include <sys/wait.h> @@ -63,6 +65,49 @@ TEST(Process, TerminationFailure) ASSERT_EQ(p.GetState(), Process::FINISHED_FAILURE); } +TEST(Process, ChildTearDown) +{ + SCOPED_TRACE("TESTCASE: ensure child process dies when parent does"); + + int pipefd[2]; + ASSERT_NE(pipe(pipefd), -1); + + /* Fork, the child will spawn a Process, write that Process's PID to a + pipe and then kill itself. The parent checks that the child was + terminated when the parent was killed. + */ + pid_t pid = fork(); + if (pid == 0) { /* child */ + close(pipefd[0]); + + Process p; + p.Start("sleep", "1000", NULL); /* forks another child */ + ASSERT_GT(p.Pid(), 0); + + char *buffer; + ASSERT_GT(asprintf(&buffer, "%d", p.Pid()), 0); + ASSERT_EQ(write(pipefd[1], buffer, strlen(buffer)), (int)strlen(buffer)); + close(pipefd[1]); + + raise(SIGKILL); + } else { /* parent */ + close(pipefd[1]); + + char buffer[20] = {0}; + ASSERT_GT(read(pipefd[0], buffer, sizeof(buffer)), 0); + close(pipefd[0]); + + pid_t child_pid = atoi(buffer); + for (int i = 0; i < 10; i++) { + if (kill(child_pid, 0) != -1) + usleep(100); + + } + ASSERT_EQ(kill(child_pid, 0), -1); + ASSERT_EQ(errno, ESRCH); + } +} + int main(int argc, char *argv[]) { testing::InitGoogleTest(&argc, argv); |