• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <stdlib.h>
2 #include <string.h>
3 #include <errno.h>
4 #include <signal.h>
5 #include <time.h>
6 #include <sys/types.h>
7 #include <sys/wait.h>
8 #include <sys/time.h>
9 #include <sys/resource.h>
10 #include <unistd.h>
11 #include "test.h"
12 
handler(int s)13 static void handler(int s)
14 {
15 }
16 
start(char * wrap,char * argv[])17 static int start(char *wrap, char *argv[])
18 {
19 	int pid;
20 
21 	pid = fork();
22 	if (pid == 0) {
23 		t_setrlim(RLIMIT_STACK, 100*1024);
24 		if (*wrap) {
25 			argv--;
26 			argv[0] = wrap;
27 		}
28 		execv(argv[0], argv);
29 		t_error("%s exec failed: %s\n", argv[0], strerror(errno));
30 		exit(1);
31 	}
32 	return pid;
33 }
34 
usage(char * argv[])35 static void usage(char *argv[])
36 {
37 	t_error("usage: %s [-t timeoutsec] [-w wrapcmd] cmd [args..]\n", argv[0]);
38 	exit(-1);
39 }
40 
main(int argc,char * argv[])41 int main(int argc, char *argv[])
42 {
43 	char *wrap = "";
44 	int timeoutsec = 5;
45 	int timeout = 0;
46 	int status;
47 	sigset_t set;
48 	int opt;
49 	int pid;
50 
51 	while ((opt = getopt(argc, argv, "w:t:")) != -1) {
52 		switch (opt) {
53 		case 'w':
54 			wrap = optarg;
55 			break;
56 		case 't':
57 			timeoutsec = atoi(optarg);
58 			break;
59 		default:
60 			usage(argv);
61 		}
62 	}
63 	if (optind >= argc)
64 		usage(argv);
65 	argv += optind;
66 	sigemptyset(&set);
67 	sigaddset(&set, SIGCHLD);
68 	sigprocmask(SIG_BLOCK, &set, 0);
69 	signal(SIGCHLD, handler);
70 	pid = start(wrap, argv);
71 	if (pid == -1) {
72 		t_error("%s fork failed: %s\n", argv[0], strerror(errno));
73 		t_printf("FAIL %s [internal]\n", argv[0]);
74 		return -1;
75 	}
76 	if (sigtimedwait(&set, 0, &(struct timespec){timeoutsec,0}) == -1) {
77 		if (errno == EAGAIN)
78 			timeout = 1;
79 		else
80 			t_error("%s sigtimedwait failed: %s\n", argv[0], strerror(errno));
81 		if (kill(pid, SIGKILL) == -1)
82 			t_error("%s kill failed: %s\n", argv[0], strerror(errno));
83 	}
84 	if (waitpid(pid, &status, 0) != pid) {
85 		t_error("%s waitpid failed: %s\n", argv[0], strerror(errno));
86 		t_printf("FAIL %s [internal]\n", argv[0]);
87 		return -1;
88 	}
89 	if (WIFEXITED(status)) {
90 		if (WEXITSTATUS(status) == 0)
91 			return t_status;
92 		t_printf("FAIL %s [status %d]\n", argv[0], WEXITSTATUS(status));
93 	} else if (timeout) {
94 		t_printf("FAIL %s [timed out]\n", argv[0]);
95 	} else if (WIFSIGNALED(status)) {
96 		t_printf("FAIL %s [signal %s]\n", argv[0], strsignal(WTERMSIG(status)));
97 	} else
98 		t_printf("FAIL %s [unknown]\n", argv[0]);
99 	return 1;
100 }
101