1f08c3bdfSopenharmony_ci/* 2f08c3bdfSopenharmony_ci * Copyright (c) 2004, Bull S.A.. All rights reserved. 3f08c3bdfSopenharmony_ci * Created by: Sebastien Decugis 4f08c3bdfSopenharmony_ci 5f08c3bdfSopenharmony_ci * This program is free software; you can redistribute it and/or modify it 6f08c3bdfSopenharmony_ci * under the terms of version 2 of the GNU General Public License as 7f08c3bdfSopenharmony_ci * published by the Free Software Foundation. 8f08c3bdfSopenharmony_ci * 9f08c3bdfSopenharmony_ci * This program is distributed in the hope that it would be useful, but 10f08c3bdfSopenharmony_ci * WITHOUT ANY WARRANTY; without even the implied warranty of 11f08c3bdfSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12f08c3bdfSopenharmony_ci * 13f08c3bdfSopenharmony_ci * You should have received a copy of the GNU General Public License along 14f08c3bdfSopenharmony_ci * with this program; if not, write the Free Software Foundation, Inc., 15f08c3bdfSopenharmony_ci * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16f08c3bdfSopenharmony_ci 17f08c3bdfSopenharmony_ci * This utility software allows to run any executable file with a timeout limit. 18f08c3bdfSopenharmony_ci * The syntax is: 19f08c3bdfSopenharmony_ci * $ ./t0 n exe arglist 20f08c3bdfSopenharmony_ci * where n is the timeout duration in seconds, 21f08c3bdfSopenharmony_ci * exe is the executable filename to run, 22f08c3bdfSopenharmony_ci * arglist is the arguments to be passed to executable. 23f08c3bdfSopenharmony_ci * 24f08c3bdfSopenharmony_ci * The use of this utility is intended to be "transparent", which means 25f08c3bdfSopenharmony_ci * everything is as if 26f08c3bdfSopenharmony_ci * $ exe arglist 27f08c3bdfSopenharmony_ci * had been called, and a call to "alarm(n)" had been added inside exe's main. 28f08c3bdfSopenharmony_ci * 29f08c3bdfSopenharmony_ci * SPECIAL CASE: 30f08c3bdfSopenharmony_ci * $ ./t0 0 31f08c3bdfSopenharmony_ci * Here another arg is not required. This special case will return immediatly 32f08c3bdfSopenharmony_ci * as if it has been timedout. This is useful to check a timeout return code value. 33f08c3bdfSopenharmony_ci * 34f08c3bdfSopenharmony_ci */ 35f08c3bdfSopenharmony_ci 36f08c3bdfSopenharmony_ci#include <sys/types.h> 37f08c3bdfSopenharmony_ci#include <sys/wait.h> 38f08c3bdfSopenharmony_ci#include <errno.h> 39f08c3bdfSopenharmony_ci#include <pthread.h> 40f08c3bdfSopenharmony_ci#include <signal.h> 41f08c3bdfSopenharmony_ci#include <stdio.h> 42f08c3bdfSopenharmony_ci#include <stdlib.h> 43f08c3bdfSopenharmony_ci#include <string.h> 44f08c3bdfSopenharmony_ci#include <unistd.h> 45f08c3bdfSopenharmony_ci 46f08c3bdfSopenharmony_cistatic pid_t pid_to_monitor; 47f08c3bdfSopenharmony_ci 48f08c3bdfSopenharmony_cistatic void sighandler(int sig) 49f08c3bdfSopenharmony_ci{ 50f08c3bdfSopenharmony_ci if (0 < pid_to_monitor) { 51f08c3bdfSopenharmony_ci if (kill(pid_to_monitor, SIGKILL) == -1) { 52f08c3bdfSopenharmony_ci perror("kill(.., SIGKILL) failed"); 53f08c3bdfSopenharmony_ci abort(); /* Something's really screwed up if we get here. */ 54f08c3bdfSopenharmony_ci } 55f08c3bdfSopenharmony_ci waitpid(pid_to_monitor, NULL, WNOHANG); 56f08c3bdfSopenharmony_ci } 57f08c3bdfSopenharmony_ci exit(SIGALRM + 128); 58f08c3bdfSopenharmony_ci} 59f08c3bdfSopenharmony_ci 60f08c3bdfSopenharmony_ciint main(int argc, char *argv[]) 61f08c3bdfSopenharmony_ci{ 62f08c3bdfSopenharmony_ci int status, timeout; 63f08c3bdfSopenharmony_ci 64f08c3bdfSopenharmony_ci /* Special case: t0 0 */ 65f08c3bdfSopenharmony_ci if (argc == 2 && (strncmp(argv[1], "0", 1) == 0)) { 66f08c3bdfSopenharmony_ci kill(getpid(), SIGALRM); 67f08c3bdfSopenharmony_ci exit(1); 68f08c3bdfSopenharmony_ci } 69f08c3bdfSopenharmony_ci 70f08c3bdfSopenharmony_ci /* General case */ 71f08c3bdfSopenharmony_ci if (argc < 3) { 72f08c3bdfSopenharmony_ci printf("\nUsage: \n"); 73f08c3bdfSopenharmony_ci printf(" $ %s n exe arglist\n", argv[0]); 74f08c3bdfSopenharmony_ci printf(" $ %s 0\n", argv[0]); 75f08c3bdfSopenharmony_ci printf("\nWhere:\n"); 76f08c3bdfSopenharmony_ci printf(" n is the timeout duration in seconds,\n"); 77f08c3bdfSopenharmony_ci printf(" exe is the executable filename to run,\n"); 78f08c3bdfSopenharmony_ci printf 79f08c3bdfSopenharmony_ci (" arglist is the arguments to be passed to executable.\n\n"); 80f08c3bdfSopenharmony_ci printf 81f08c3bdfSopenharmony_ci (" The second use case will emulate an immediate timeout.\n\n"); 82f08c3bdfSopenharmony_ci exit(1); 83f08c3bdfSopenharmony_ci } 84f08c3bdfSopenharmony_ci 85f08c3bdfSopenharmony_ci timeout = atoi(argv[1]); 86f08c3bdfSopenharmony_ci if (timeout < 1) { 87f08c3bdfSopenharmony_ci fprintf(stderr, 88f08c3bdfSopenharmony_ci "Invalid timeout value \"%s\". Timeout must be a positive integer.\n", 89f08c3bdfSopenharmony_ci argv[1]); 90f08c3bdfSopenharmony_ci exit(1); 91f08c3bdfSopenharmony_ci } 92f08c3bdfSopenharmony_ci 93f08c3bdfSopenharmony_ci if (signal(SIGALRM, sighandler) == SIG_ERR) { 94f08c3bdfSopenharmony_ci perror("signal failed"); 95f08c3bdfSopenharmony_ci exit(1); 96f08c3bdfSopenharmony_ci } 97f08c3bdfSopenharmony_ci 98f08c3bdfSopenharmony_ci alarm(timeout); 99f08c3bdfSopenharmony_ci 100f08c3bdfSopenharmony_ci switch (pid_to_monitor = fork()) { 101f08c3bdfSopenharmony_ci case -1: 102f08c3bdfSopenharmony_ci perror("fork failed"); 103f08c3bdfSopenharmony_ci exit(1); 104f08c3bdfSopenharmony_ci case 0: 105f08c3bdfSopenharmony_ci setpgid(0, 0); 106f08c3bdfSopenharmony_ci execvp(argv[2], &argv[2]); 107f08c3bdfSopenharmony_ci perror("execvp failed"); 108f08c3bdfSopenharmony_ci exit(1); 109f08c3bdfSopenharmony_ci default: 110f08c3bdfSopenharmony_ci 111f08c3bdfSopenharmony_ci for (;;) { 112f08c3bdfSopenharmony_ci if (waitpid(pid_to_monitor, &status, 0) == 113f08c3bdfSopenharmony_ci pid_to_monitor) 114f08c3bdfSopenharmony_ci break; 115f08c3bdfSopenharmony_ci else if (errno == EINTR) { 116f08c3bdfSopenharmony_ci perror("waitpid failed"); 117f08c3bdfSopenharmony_ci exit(1); 118f08c3bdfSopenharmony_ci } 119f08c3bdfSopenharmony_ci } 120f08c3bdfSopenharmony_ci /* Relay the child's status back to run-tests.sh */ 121f08c3bdfSopenharmony_ci if (WIFEXITED(status)) 122f08c3bdfSopenharmony_ci exit(WEXITSTATUS(status)); 123f08c3bdfSopenharmony_ci else if (WIFSIGNALED(status)) 124f08c3bdfSopenharmony_ci exit(WTERMSIG(status) + 128); 125f08c3bdfSopenharmony_ci 126f08c3bdfSopenharmony_ci } 127f08c3bdfSopenharmony_ci 128f08c3bdfSopenharmony_ci exit(1); 129f08c3bdfSopenharmony_ci} 130