source: tools/watchdog.c@ 1cf2a9b

ADT arm-eh ast-experimental enum forall-pointer-decay jacob/cs343-translation new-ast new-ast-unique-expr pthread-emulation qualifiedEnum
Last change on this file since 1cf2a9b was 7bdcac1, checked in by Thierry Delisle <tdelisle@…>, 7 years ago

Added the option to make longrun tests run until failure

  • Property mode set to 100644
File size: 3.3 KB
Line 
1#include <errno.h>
2#include <fcntl.h>
3#include <getopt.h>
4#include <signal.h>
5#include <stdbool.h>
6#include <stdio.h>
7#include <stdlib.h>
8#include <string.h>
9#include <sys/select.h>
10#include <sys/stat.h>
11#include <sys/types.h>
12#include <sys/wait.h>
13#include <unistd.h>
14
15char * this_cmd = NULL;
16
17void parse_args(int argc, char * argv[]);
18int run();
19void printcmd();
20
21int main(int argc, char * argv[]) {
22 parse_args(argc, argv);
23
24 int retcode = run();
25 if( !WIFEXITED(retcode) ) {
26 printf("Child Error : %d ", retcode); printcmd();
27 return retcode;
28 }
29
30 printf("Child exited normally "); printcmd();
31 return 0;
32}
33
34void usage( FILE * out, int code ) {
35 fprintf(out, "%s [OPTION] [--] N CMD\n", this_cmd);
36 fprintf(out, "Run command, killing it if it doesn't print for more than 5 continuous seconds\n\n");
37 fprintf(out, "\t-h,--help\tprint this usage message\n");
38 exit(code);
39}
40
41char ** cmd_to_run = NULL;
42pid_t child_pid = 0;
43int pipe_fds[2];
44
45void arg_error(void) {
46 fprintf(stderr,"\n");
47 usage(stderr, 1);
48}
49
50void parse_args(int argc, char * argv[]) {
51 this_cmd = argv[0];
52
53 enum { Help, };
54 static struct option long_opts[] = {
55 { "help", no_argument, 0, Help },
56 { 0, 0, 0, 0 }
57 }; // long_opts
58 int long_index;
59
60 int c;
61 while ( (c = getopt_long( argc, argv, "h", long_opts, &long_index)) != -1 ) {
62 switch ( c ) {
63 case Help:
64 case 'h':
65 usage(stdout, 0);
66 break;
67 default:
68 arg_error();
69 break;
70 } // switch
71 } // while
72
73 if( argc < optind + 1 ) {
74 fprintf(stderr, "Too few arguments\n");
75 arg_error();
76 }
77
78 cmd_to_run = argv + optind;
79}
80
81static void exit_handler (__attribute__((unused)) int a, __attribute__((unused)) void * b) {
82 close(pipe_fds[0]);
83 if(child_pid != 0) kill(child_pid, SIGKILL);
84}
85
86#define checked(call, ...) ({int ret = call(__VA_ARGS__); if (ret == -1) { perror(#call); exit(1); } ret;})
87
88void run_child();
89void make_noblock(int fd);
90void sink(int fd);
91int waitfd(int fd);
92
93int run() {
94 on_exit(exit_handler, NULL);
95 checked(pipe, pipe_fds);
96
97 printf("Watching command: "); printcmd();
98
99 child_pid = checked(fork);
100 if (child_pid == 0) { run_child(); }
101
102 close(pipe_fds[1]);
103 make_noblock(pipe_fds[0]);
104
105 int status;
106 while(waitpid(child_pid, &status, WNOHANG) == 0) {
107 if(waitfd(pipe_fds[0]) == 0) {
108 printf("Child Deadlocked "); printcmd();
109 exit(127);
110 }
111 sink(pipe_fds[0]);
112 }
113
114 child_pid = 0;
115 return status;
116
117 return 0;
118}
119
120void make_noblock(int fd) {
121 int flags = fcntl(fd, F_GETFL);
122 flags |= O_NONBLOCK;
123 fcntl(fd, F_SETFL, flags );
124}
125
126void sink(int fd) {
127 char buff[100];
128 int len = 100;
129 int rv;
130 do {
131 rv = read( fd, buff, len );
132 }
133 while(rv > 0);
134}
135
136int waitfd(int fd) {
137 fd_set set;
138 FD_ZERO(&set);
139 FD_SET(fd, &set);
140
141 struct timeval timeout;
142 timeout.tv_sec = 5;
143 timeout.tv_usec = 0;
144
145 int rv = select(fd + 1, &set, NULL, NULL, &timeout);
146 if(rv == -1) {
147 perror("select\n");
148 exit(1);
149 }
150 return rv;
151}
152
153void run_child() {
154 /* This is the child process. */
155 while ((dup2(pipe_fds[1], STDOUT_FILENO) == -1) && (errno == EINTR));
156
157 close(pipe_fds[1]);
158 close(pipe_fds[0]);
159
160 execvp ( *cmd_to_run, cmd_to_run);
161
162 /* The execvp function returns only if an error occurs. */
163 fprintf(stderr, "an error occurred in execvp\n");
164 abort ();
165}
166
167void printcmd() {
168 if(!cmd_to_run) return;
169 char ** cmd = cmd_to_run;
170 while (*cmd) {
171 printf("%s ", *cmd);
172 cmd++;
173 }
174 printf("\n");
175}
Note: See TracBrowser for help on using the repository browser.