11c5ac21333f543680ce306d46f287d62c175d873mridge/* Repeatedly run a program for a given length of time. */
21c5ac21333f543680ce306d46f287d62c175d873mridge
31e6f5a673655551de5734ff31ef48cd63b604e6dGarrett Cooper/*
41c5ac21333f543680ce306d46f287d62c175d873mridge * Copyright (C) 2003-2006 IBM
51e6f5a673655551de5734ff31ef48cd63b604e6dGarrett Cooper *
61c5ac21333f543680ce306d46f287d62c175d873mridge * This program is free software; you can redistribute it and/or
71c5ac21333f543680ce306d46f287d62c175d873mridge * modify it under the terms of the GNU General Public License as
81c5ac21333f543680ce306d46f287d62c175d873mridge * published by the Free Software Foundation; either version 2 of the
91c5ac21333f543680ce306d46f287d62c175d873mridge * License, or (at your option) any later version.
101c5ac21333f543680ce306d46f287d62c175d873mridge *
111c5ac21333f543680ce306d46f287d62c175d873mridge * This program is distributed in the hope that it will be useful, but
121c5ac21333f543680ce306d46f287d62c175d873mridge * WITHOUT ANY WARRANTY; without even the implied warranty of
131c5ac21333f543680ce306d46f287d62c175d873mridge * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
141c5ac21333f543680ce306d46f287d62c175d873mridge * General Public License for more details.
151e6f5a673655551de5734ff31ef48cd63b604e6dGarrett Cooper *
161c5ac21333f543680ce306d46f287d62c175d873mridge * You should have received a copy of the GNU General Public License
171c5ac21333f543680ce306d46f287d62c175d873mridge * along with this program; if not, write to the Free Software
181c5ac21333f543680ce306d46f287d62c175d873mridge * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
191c5ac21333f543680ce306d46f287d62c175d873mridge * 02111-1307, USA.
201c5ac21333f543680ce306d46f287d62c175d873mridge */
211c5ac21333f543680ce306d46f287d62c175d873mridge
221c5ac21333f543680ce306d46f287d62c175d873mridge#include <stdio.h>
2332cc0acd99e36836b13056c6d0e3e62a115678f3vapier#include <string.h>
241c5ac21333f543680ce306d46f287d62c175d873mridge#include <strings.h>
251c5ac21333f543680ce306d46f287d62c175d873mridge#include <stdlib.h>
261c5ac21333f543680ce306d46f287d62c175d873mridge#include <unistd.h>
271c5ac21333f543680ce306d46f287d62c175d873mridge#include <sys/types.h>
281c5ac21333f543680ce306d46f287d62c175d873mridge#include <sys/wait.h>
291c5ac21333f543680ce306d46f287d62c175d873mridge
301c5ac21333f543680ce306d46f287d62c175d873mridge#include "debug.h"
311c5ac21333f543680ce306d46f287d62c175d873mridge
321c5ac21333f543680ce306d46f287d62c175d873mridgestatic int res = 0;
331c5ac21333f543680ce306d46f287d62c175d873mridgestatic char *progname;
341c5ac21333f543680ce306d46f287d62c175d873mridgestatic pid_t test_pgrp;
3598d8d3aa130f8ec92171fb7e5bcd02d645bac110Li Wangstatic FILE *out;
361c5ac21333f543680ce306d46f287d62c175d873mridge
37354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaostatic void int_func(int signum)
38354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao{
3998d8d3aa130f8ec92171fb7e5bcd02d645bac110Li Wang	pounder_fprintf(out,
40354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			"%s: Killed by interrupt.  Last exit code = %d.\n",
41354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			progname, res);
421c5ac21333f543680ce306d46f287d62c175d873mridge	kill(-test_pgrp, SIGTERM);
431c5ac21333f543680ce306d46f287d62c175d873mridge	exit(res);
441c5ac21333f543680ce306d46f287d62c175d873mridge}
45354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
46354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaostatic void alarm_func(int signum)
47354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao{
4898d8d3aa130f8ec92171fb7e5bcd02d645bac110Li Wang	pounder_fprintf(out, "%s: Killed by timer.  Last exit code = %d.\n",
49354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			progname, res);
501c5ac21333f543680ce306d46f287d62c175d873mridge	kill(-test_pgrp, SIGTERM);
511c5ac21333f543680ce306d46f287d62c175d873mridge	exit(res);
521c5ac21333f543680ce306d46f287d62c175d873mridge}
531c5ac21333f543680ce306d46f287d62c175d873mridge
541c5ac21333f543680ce306d46f287d62c175d873mridge/*
551c5ac21333f543680ce306d46f287d62c175d873mridgestatic void term_func(int signum) {
561c5ac21333f543680ce306d46f287d62c175d873mridge	exit(res);
571c5ac21333f543680ce306d46f287d62c175d873mridge}
581c5ac21333f543680ce306d46f287d62c175d873mridge*/
591c5ac21333f543680ce306d46f287d62c175d873mridge
60354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaoint main(int argc, char *argv[])
61354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao{
621c5ac21333f543680ce306d46f287d62c175d873mridge	int secs, stat;
631c5ac21333f543680ce306d46f287d62c175d873mridge	pid_t pid;
641c5ac21333f543680ce306d46f287d62c175d873mridge	unsigned int revs = 0;
651c5ac21333f543680ce306d46f287d62c175d873mridge	struct sigaction zig;
6686db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang	int use_max_failures = 0;
6786db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang	int max_failures = 0;
6886db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang	int fail_counter = 1;
691e6f5a673655551de5734ff31ef48cd63b604e6dGarrett Cooper
701c5ac21333f543680ce306d46f287d62c175d873mridge	if (argc < 3) {
71354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		printf
72354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		    ("Usage: %s [-m max_failures] time_in_sec command [args]\n",
73354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		     argv[0]);
741c5ac21333f543680ce306d46f287d62c175d873mridge		exit(1);
751c5ac21333f543680ce306d46f287d62c175d873mridge	}
7686db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang	//by default, set max_failures to whatever the env variable $MAX_FAILURES is
77354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	char *max_failures_env = getenv("MAX_FAILURES");
78354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	max_failures = atoi(max_failures_env);
7986db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang
8086db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang	//if the -m option is used when calling timed_loop, override max_failures
8186db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang	//specified by $MAX_FAILURES with the given argument instead
8286db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang	if (argc > 4 && strcmp(argv[1], "-m") == 0) {
8337550cf5a86c7ca7424a2a318dd64e550f13f5dfChris Dearman		if ((max_failures = atoi(argv[2])) >= 0) {
8486db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang			use_max_failures = 1;
85354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		} else {
86354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			printf
87354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			    ("Usage: %s [-m max_failures] time_in_sec command [args]\n",
88354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			     argv[0]);
89354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			printf
90354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			    ("max_failures should be a nonnegative integer\n");
9186db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang			exit(1);
9286db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang		}
9386db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang	}
9486db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang
9598d8d3aa130f8ec92171fb7e5bcd02d645bac110Li Wang	out = stdout;
961c5ac21333f543680ce306d46f287d62c175d873mridge
9786db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang	if (use_max_failures) {
9886db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang		progname = rindex(argv[4], '/');
9986db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang		if (progname == NULL) {
10086db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang			progname = argv[4];
10186db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang		} else {
10286db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang			progname++;
10386db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang		}
104354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	} else {
10586db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang		progname = rindex(argv[2], '/');
10686db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang		if (progname == NULL) {
10786db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang			progname = argv[2];
10886db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang		} else {
10986db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang			progname++;
11086db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang		}
1111c5ac21333f543680ce306d46f287d62c175d873mridge	}
1121c5ac21333f543680ce306d46f287d62c175d873mridge
1131c5ac21333f543680ce306d46f287d62c175d873mridge	/* Set up signals */
11432cc0acd99e36836b13056c6d0e3e62a115678f3vapier	memset(&zig, 0x00, sizeof(zig));
1151c5ac21333f543680ce306d46f287d62c175d873mridge	zig.sa_handler = alarm_func;
1161c5ac21333f543680ce306d46f287d62c175d873mridge	sigaction(SIGALRM, &zig, NULL);
1171c5ac21333f543680ce306d46f287d62c175d873mridge	zig.sa_handler = int_func;
1181c5ac21333f543680ce306d46f287d62c175d873mridge	sigaction(SIGINT, &zig, NULL);
1191c5ac21333f543680ce306d46f287d62c175d873mridge	sigaction(SIGTERM, &zig, NULL);
1201c5ac21333f543680ce306d46f287d62c175d873mridge
1211c5ac21333f543680ce306d46f287d62c175d873mridge	/* set up process groups so that we can kill the
1221c5ac21333f543680ce306d46f287d62c175d873mridge	 * loop test and descendants easily */
1231c5ac21333f543680ce306d46f287d62c175d873mridge
12486db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang	if (use_max_failures) {
12586db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang		secs = atoi(argv[3]);
126354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	} else {
12786db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang		secs = atoi(argv[1]);
12886db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang	}
1291c5ac21333f543680ce306d46f287d62c175d873mridge	alarm(secs);
1301c5ac21333f543680ce306d46f287d62c175d873mridge
1311c5ac21333f543680ce306d46f287d62c175d873mridge	while (1) {
13298d8d3aa130f8ec92171fb7e5bcd02d645bac110Li Wang		pounder_fprintf(out, "%s: %s loop #%d.\n", progname,
133354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				start_msg, revs++);
1341c5ac21333f543680ce306d46f287d62c175d873mridge		pid = fork();
1351c5ac21333f543680ce306d46f287d62c175d873mridge		if (pid == 0) {
1361c5ac21333f543680ce306d46f287d62c175d873mridge			if (setpgrp() < 0) {
1371c5ac21333f543680ce306d46f287d62c175d873mridge				perror("setpgid");
1381c5ac21333f543680ce306d46f287d62c175d873mridge			}
1391c5ac21333f543680ce306d46f287d62c175d873mridge			// run the program
14086db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang			if (use_max_failures) {
14186db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang				if (argc > 5) {
14286db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang					stat = execvp(argv[4], &argv[4]);
14386db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang				} else {
14486db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang					stat = execvp(argv[4], &argv[4]);
14586db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang				}
14686db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang
14786db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang				perror(argv[4]);
148354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			} else {
14986db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang				if (argc > 3) {
15086db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang					stat = execvp(argv[2], &argv[2]);
15186db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang				} else {
15286db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang					stat = execvp(argv[2], &argv[2]);
15386db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang				}
15486db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang
15586db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang				perror(argv[2]);
1561c5ac21333f543680ce306d46f287d62c175d873mridge			}
1571c5ac21333f543680ce306d46f287d62c175d873mridge
1581c5ac21333f543680ce306d46f287d62c175d873mridge			exit(-1);
1591c5ac21333f543680ce306d46f287d62c175d873mridge		}
1601e6f5a673655551de5734ff31ef48cd63b604e6dGarrett Cooper
1611c5ac21333f543680ce306d46f287d62c175d873mridge		/* save the pgrp of the spawned process */
1621c5ac21333f543680ce306d46f287d62c175d873mridge		test_pgrp = pid;
1631c5ac21333f543680ce306d46f287d62c175d873mridge
1641c5ac21333f543680ce306d46f287d62c175d873mridge		// wait for it to be done
1651c5ac21333f543680ce306d46f287d62c175d873mridge		if (waitpid(pid, &stat, 0) != pid) {
1661c5ac21333f543680ce306d46f287d62c175d873mridge			perror("waitpid");
1671c5ac21333f543680ce306d46f287d62c175d873mridge			exit(1);
1681c5ac21333f543680ce306d46f287d62c175d873mridge		}
1691c5ac21333f543680ce306d46f287d62c175d873mridge		// interrogate it
1701c5ac21333f543680ce306d46f287d62c175d873mridge		if (WIFSIGNALED(stat)) {
17198d8d3aa130f8ec92171fb7e5bcd02d645bac110Li Wang			pounder_fprintf(out, "%s: %s on signal %d.\n",
172354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao					progname, fail_msg, WTERMSIG(stat));
1731c5ac21333f543680ce306d46f287d62c175d873mridge			res = 255;
1741c5ac21333f543680ce306d46f287d62c175d873mridge		} else {
1751c5ac21333f543680ce306d46f287d62c175d873mridge			res = WEXITSTATUS(stat);
1761c5ac21333f543680ce306d46f287d62c175d873mridge			if (res == 0) {
17798d8d3aa130f8ec92171fb7e5bcd02d645bac110Li Wang				pounder_fprintf(out, "%s: %s.\n", progname,
178354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao						pass_msg);
1791c5ac21333f543680ce306d46f287d62c175d873mridge			} else if (res < 0 || res == 255) {
18098d8d3aa130f8ec92171fb7e5bcd02d645bac110Li Wang				pounder_fprintf(out,
181354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao						"CHECK %s: %s with code %d.\n",
182354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao						progname, abort_msg, res);
1831c5ac21333f543680ce306d46f287d62c175d873mridge				exit(-1);
1841c5ac21333f543680ce306d46f287d62c175d873mridge				// FIXME: add test to blacklist
1851c5ac21333f543680ce306d46f287d62c175d873mridge			} else {
18698d8d3aa130f8ec92171fb7e5bcd02d645bac110Li Wang				pounder_fprintf(out,
187354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao						"%s: %s with code %d.\n",
188354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao						progname, fail_msg, res);
18986db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang				if (max_failures > 0) {
19086db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang					if (++fail_counter > max_failures) {
19186db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang						exit(-1);
19286db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang					}
19386db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang				}
1941c5ac21333f543680ce306d46f287d62c175d873mridge			}
1951c5ac21333f543680ce306d46f287d62c175d873mridge		}
1961c5ac21333f543680ce306d46f287d62c175d873mridge	}
19786db0c171384b39671502c5e4e46c07da8c4f51fLucy Liang}
198