]> granicus.if.org Git - check/commitdiff
Catch SIGINT and SIGTERM and kill running tests
authorbrarcher <brarcher@64e312b2-a51f-0410-8e61-82d0ca0eb02a>
Thu, 7 May 2015 03:16:26 +0000 (03:16 +0000)
committerbrarcher <brarcher@64e312b2-a51f-0410-8e61-82d0ca0eb02a>
Thu, 7 May 2015 03:16:26 +0000 (03:16 +0000)
Tests are forked and placed into their own process group.
If the test runner process receives a terminal signal it
exits but the test continue running. This could result
in test processes running indefinitely if they do not
exit themselves.

This changes catches SIGINT and SIGTERM signals and kills
the test processes.

Note that other signals, such as SIGSEGV and SIGFPE will still
result in test processes being leaked.

This code is based on that in patch #52.

git-svn-id: svn+ssh://svn.code.sf.net/p/check/code/trunk@1203 64e312b2-a51f-0410-8e61-82d0ca0eb02a

AUTHORS
NEWS
src/check_run.c

diff --git a/AUTHORS b/AUTHORS
index 3445b3060d22cdf6488588714c18216fb50c7386..33447a6a8b5829dd0933b39a5fba30c8cf4fe954 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -52,6 +52,7 @@ Contributors:
     Michael Piszczek      (misc cleanup)
     Stewart Brodie        (bug fix: no fork mode failure reporting with teardowns)
     Michał Dębski         (Use mkstemp() if available instead of tmpfile() or tempnam())
+    Sebastian Dröge       (Kill running tests if SIGTERM or SIGINT are caught in test runner)
 
 Anybody who has contributed code to Check or Check's build system is
 considered an author.  Send patches to this file to 
diff --git a/NEWS b/NEWS
index b6aac9543bc95f90affa40f44811faf71c09112c..15864b4d040619cfb27bf6543641c32d407c6a4d 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,10 @@
 In Development:
 # Mentioning Check 0.9.14 for now, to fix distcheck target until next release
 
+* If the test runner process catches a SIGTERM or SIGINT signal the running
+  tests are now also killed.
+  Patch #52.
+
 * If Check is compiled without support for fork(), the behavior of
   functions which require fork() to be useful have been changed.
   Functions that attempt to set CK_FORK mode are no-ops,
index 911ccfe2a43088381bf86eb6ea08d17a2dba6d0c..dd661a721e3e3a867c8db64680766a12d181192d 100644 (file)
@@ -96,6 +96,8 @@ static int waserror(int status, int expected_signal);
 
 static int alarm_received;
 static pid_t group_pid;
+static struct sigaction sigint_old_action;
+static struct sigaction sigterm_old_action;
 
 static void CK_ATTRIBUTE_UNUSED sig_handler(int sig_nr)
 {
@@ -105,6 +107,31 @@ static void CK_ATTRIBUTE_UNUSED sig_handler(int sig_nr)
             alarm_received = 1;
             killpg(group_pid, SIGKILL);
             break;
+        case SIGTERM:
+        case SIGINT:
+        {
+            pid_t own_group_pid;
+            int child_sig = SIGTERM;
+
+            if (sig_nr == SIGINT)
+            {
+                child_sig = SIGKILL;
+                sigaction(SIGINT, &sigint_old_action, NULL);
+            }
+            else
+            {
+                sigaction(SIGTERM, &sigterm_old_action, NULL);
+            }
+
+            killpg(group_pid, child_sig);
+
+            /* POSIX says that calling killpg(0)
+             * does not necessarily mean to call it on the callers
+             * group pid! */
+            own_group_pid = getpgrp();
+            killpg(own_group_pid, sig_nr);
+            break;
+        }
         default:
             eprintf("Unhandled signal: %d", __FILE__, __LINE__, sig_nr);
             break;
@@ -718,8 +745,10 @@ void srunner_run(SRunner * sr, const char *sname, const char *tcname,
                  enum print_output print_mode)
 {
 #if defined(HAVE_SIGACTION) && defined(HAVE_FORK)
-    struct sigaction old_action;
-    struct sigaction new_action;
+    static struct sigaction sigalarm_old_action;
+    static struct sigaction sigalarm_new_action;
+    static struct sigaction sigint_new_action;
+    static struct sigaction sigterm_new_action;
 #endif /* HAVE_SIGACTION && HAVE_FORK */
 
     /*  Get the selected test suite and test case from the
@@ -737,15 +766,25 @@ void srunner_run(SRunner * sr, const char *sname, const char *tcname,
                 __FILE__, __LINE__, print_mode);
     }
 #if defined(HAVE_SIGACTION) && defined(HAVE_FORK)
-    memset(&new_action, 0, sizeof new_action);
-    new_action.sa_handler = sig_handler;
-    sigaction(SIGALRM, &new_action, &old_action);
+    memset(&sigalarm_new_action, 0, sizeof(sigalarm_new_action));
+    sigalarm_new_action.sa_handler = sig_handler;
+    sigaction(SIGALRM, &sigalarm_new_action, &sigalarm_old_action);
+
+    memset(&sigint_new_action, 0, sizeof(sigint_new_action));
+    sigint_new_action.sa_handler = sig_handler;
+    sigaction(SIGINT, &sigint_new_action, &sigint_old_action);
+
+    memset(&sigterm_new_action, 0, sizeof(sigterm_new_action));
+    sigterm_new_action.sa_handler = sig_handler;
+    sigaction(SIGTERM, &sigterm_new_action, &sigterm_old_action);
 #endif /* HAVE_SIGACTION && HAVE_FORK */
     srunner_run_init(sr, print_mode);
     srunner_iterate_suites(sr, sname, tcname, print_mode);
     srunner_run_end(sr, print_mode);
 #if defined(HAVE_SIGACTION) && defined(HAVE_FORK)
-    sigaction(SIGALRM, &old_action, NULL);
+    sigaction(SIGALRM, &sigalarm_old_action, NULL);
+    sigaction(SIGINT, &sigint_old_action, NULL);
+    sigaction(SIGTERM, &sigterm_old_action, NULL);
 #endif /* HAVE_SIGACTION && HAVE_FORK */
 }