Skip to content

Commit

Permalink
Catch SIGINT and SIGTERM and kill running tests
Browse files Browse the repository at this point in the history
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
  • Loading branch information
brarcher committed May 7, 2015
1 parent 3ec30d2 commit d6c7064
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 6 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
@@ -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,
Expand Down
51 changes: 45 additions & 6 deletions src/check_run.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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;
Expand Down Expand Up @@ -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
Expand All @@ -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 */
}

Expand Down

0 comments on commit d6c7064

Please sign in to comment.