/* StarPU --- Runtime system for heterogeneous multicore architectures. * * Copyright (C) 2010 Université de Bordeaux 1 * * StarPU is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at * your option) any later version. * * StarPU is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * See the GNU Lesser General Public License in COPYING.LGPL for more details. */ #include #include #include #include #include #include #include #include #define DEFAULT_TIMEOUT 600 #define AUTOTEST_SKIPPED_TEST 77 static pid_t child_pid = 0; static int timeout; static void test_cleaner(int sig) { pid_t child_gid; // send signal to all loader family members fprintf(stderr, "[error] test is blocked since %d seconds. Mark it as failed\n", timeout); child_gid = getpgid(child_pid); kill(-child_gid, SIGKILL); exit(EXIT_FAILURE); } int main(int argc, char *argv[]) { int child_exit_status; char *test_name; char *test_args; int status; char *launcher; char *launcher_args; struct sigaction sa; test_args = NULL; timeout = 0; test_name = argv[1]; if (!test_name) { fprintf(stderr, "[error] Need name of program to start\n"); exit(EXIT_FAILURE); } if (strstr(test_name, "spmv/dw_block_spmv")) { test_args = (char *) malloc(150*sizeof(char)); sprintf(test_args, "%s/examples/spmv/matrix_market/examples/fidapm05.mtx", STARPU_SRC_DIR); } /* get launcher program */ launcher=getenv("STARPU_CHECK_LAUNCHER"); launcher_args=getenv("STARPU_CHECK_LAUNCHER_ARGS"); /* get user-defined iter_max value */ if (getenv("STARPU_TIMEOUT_ENV")) timeout = strtol(getenv("STARPU_TIMEOUT_ENV"), NULL, 10); if (timeout <= 0) timeout = DEFAULT_TIMEOUT; /* set SIGALARM handler */ sa.sa_flags = 0; sigemptyset(&sa.sa_mask); sa.sa_handler = test_cleaner; if (-1 == sigaction(SIGALRM, &sa, NULL)) perror("sigaction"); child_pid = fork(); if (child_pid == 0) { // get a new pgid if (setpgid(0, 0) == -1) { perror("setpgid"); fprintf(stderr, "[error] setpgid. Mark test as failed\n"); exit(EXIT_FAILURE); } if (launcher) { /* "Launchers" such as Valgrind need to be inserted * after the Libtool-generated wrapper scripts, hence * this special-case. */ const char *top_builddir = getenv ("top_builddir"); if (top_builddir != NULL) { char *argv[100]; int i=3; char libtool[strlen(top_builddir) + sizeof("libtool") + 1]; strcpy(libtool, top_builddir); strcat(libtool, "/libtool"); argv[0] = libtool; argv[1] = "--mode=execute"; argv[2] = launcher; argv[i] = strtok(launcher_args, " "); while (argv[i]) { i++; argv[i] = strtok(NULL, " "); } argv[i] = test_name; argv[i+1] = NULL; execvp(*argv, argv); } else { fprintf(stderr, "warning: $top_builddir undefined, " "so $STARPU_CHECK_LAUNCHER ignored\n"); execl(test_name, test_name, test_args, NULL); } } else execl(test_name, test_name, test_args, NULL); fprintf(stderr, "[error] '%s' failed to exec. test marked as failed\n", test_name); exit(EXIT_FAILURE); } if (child_pid == -1) { fprintf(stderr, "[error] fork. test marked as failed\n"); exit(EXIT_FAILURE); } alarm(timeout); if (child_pid == waitpid(child_pid, &child_exit_status, 0)) { if (WIFEXITED(child_exit_status)) { status = WEXITSTATUS(child_exit_status); if (status == EXIT_SUCCESS) { alarm(0); } else { if (status != AUTOTEST_SKIPPED_TEST) fprintf(stdout, "`%s' exited with return code %d\n", test_name, status); return status; } } else if (WIFSIGNALED(child_exit_status)) { fprintf(stderr, "[error] `%s' killed with signal %d; test marked as failed\n", test_name, WTERMSIG(child_exit_status)); return EXIT_FAILURE; } else { fprintf(stderr, "[error] `%s' did not terminate normally; test marked as failed\n", test_name); return EXIT_FAILURE; } } return EXIT_SUCCESS; }