0001 #ifndef _GNU_SOURCE
0002 #define _GNU_SOURCE
0003 #endif
0004
0005 #include "cgreen/runner.h"
0006 #include "cgreen/internal/runner_platform.h"
0007 #include <stdio.h>
0008 #include <unistd.h>
0009 #include <sys/wait.h>
0010 #include <signal.h>
0011 #include <stdlib.h>
0012 #include <string.h>
0013
0014 #ifdef __cplusplus
0015 namespace cgreen {
0016 #endif
0017
0018 typedef void (*sighandler_t)(int);
0019
0020 static int in_child_process(void);
0021 static int wait_for_child_process(void);
0022 static void stop(void);
0023 static void ignore_ctrl_c(void);
0024 static void allow_ctrl_c(void);
0025
0026
0027 void run_test_in_its_own_process(TestSuite *suite, CgreenTest *test, TestReporter *reporter) {
0028 (*reporter->start_test)(reporter, test->name);
0029 if (in_child_process()) {
0030 run_the_test_code(suite, test, reporter);
0031 send_reporter_completion_notification(reporter);
0032 stop();
0033 } else {
0034 const int status = wait_for_child_process();
0035 if (WIFSIGNALED(status)) {
0036
0037 const int sig = WTERMSIG(status);
0038 if (sig != SIGABRT) {
0039 char buf[128];
0040 snprintf(buf, sizeof(buf), "Test terminated with signal: %s", (const char *)strsignal(sig));
0041 (*reporter->finish_test)(reporter, test->filename, test->line, buf);
0042 return;
0043 }
0044 }
0045 (*reporter->finish_test)(reporter, test->filename, test->line, NULL);
0046 }
0047 }
0048
0049 static int in_child_process(void) {
0050 fflush(NULL);
0051 pid_t child = fork();
0052 if (child < 0) {
0053 die("Could not fork process\n");
0054 }
0055 return ! child;
0056 }
0057
0058 static int wait_for_child_process(void) {
0059 int status = 0;
0060 ignore_ctrl_c();
0061 wait(&status);
0062 allow_ctrl_c();
0063 return status;
0064 }
0065
0066 void die_in(unsigned int seconds) {
0067 sighandler_t signal_result = signal(SIGALRM, (sighandler_t)&stop);
0068 if (SIG_ERR == signal_result) {
0069 fprintf(stderr, "could not set alarm signal hander\n");
0070 return;
0071 }
0072
0073 alarm(seconds);
0074 }
0075
0076 void run_specified_test_if_child(TestSuite *suite, TestReporter *reporter){
0077
0078 (void)suite;
0079 (void)reporter;
0080 }
0081
0082 static void stop(void) {
0083 _exit(EXIT_SUCCESS);
0084 }
0085
0086 static void ignore_ctrl_c(void) {
0087 signal(SIGINT, SIG_IGN);
0088 }
0089
0090 static void allow_ctrl_c(void) {
0091 signal(SIGINT, SIG_DFL);
0092 }
0093
0094 #ifdef __cplusplus
0095 }
0096 #endif
0097
0098