[PATCH xorg-gtest 10/11] process: terminate the child if the parent dies

2012-08-16 Thread Peter Hutterer
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.hutte...@who-t.net
---
 src/process.cpp   |  5 +
 test/process-test.cpp | 45 +
 2 files changed, 50 insertions(+)

diff --git a/src/process.cpp b/src/process.cpp
index 4e903d6..d962a4c 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::vectorchar* args;
 std::vectorstd::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);
-- 
1.7.11.2

___
xorg-devel@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: http://lists.x.org/mailman/listinfo/xorg-devel


Re: [PATCH xorg-gtest 10/11] process: terminate the child if the parent dies

2012-08-16 Thread Chase Douglas

On 08/15/2012 11:36 PM, Peter Hutterer wrote:

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.hutte...@who-t.net
---
  src/process.cpp   |  5 +
  test/process-test.cpp | 45 +
  2 files changed, 50 insertions(+)

diff --git a/src/process.cpp b/src/process.cpp
index 4e903d6..d962a4c 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


I had been looking around for this ^^ for a while! It's just what we 
need to fully clean things up. Good find :).



+
  std::vectorchar* args;
  std::vectorstd::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);


Reviewed-by: Chase Douglas chase.doug...@canonical.com
___
xorg-devel@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: http://lists.x.org/mailman/listinfo/xorg-devel