1*d83cc019SAndroid Build Coastguard Worker #include <errno.h>
2*d83cc019SAndroid Build Coastguard Worker #include <fcntl.h>
3*d83cc019SAndroid Build Coastguard Worker #include <linux/watchdog.h>
4*d83cc019SAndroid Build Coastguard Worker #include <signal.h>
5*d83cc019SAndroid Build Coastguard Worker #include <stdio.h>
6*d83cc019SAndroid Build Coastguard Worker #include <stdlib.h>
7*d83cc019SAndroid Build Coastguard Worker #include <string.h>
8*d83cc019SAndroid Build Coastguard Worker #include <sys/ioctl.h>
9*d83cc019SAndroid Build Coastguard Worker #include <sys/select.h>
10*d83cc019SAndroid Build Coastguard Worker #include <sys/poll.h>
11*d83cc019SAndroid Build Coastguard Worker #include <sys/signalfd.h>
12*d83cc019SAndroid Build Coastguard Worker #include <sys/stat.h>
13*d83cc019SAndroid Build Coastguard Worker #include <sys/time.h>
14*d83cc019SAndroid Build Coastguard Worker #include <sys/types.h>
15*d83cc019SAndroid Build Coastguard Worker #include <sys/utsname.h>
16*d83cc019SAndroid Build Coastguard Worker #include <sys/wait.h>
17*d83cc019SAndroid Build Coastguard Worker #include <time.h>
18*d83cc019SAndroid Build Coastguard Worker #include <unistd.h>
19*d83cc019SAndroid Build Coastguard Worker
20*d83cc019SAndroid Build Coastguard Worker #include "igt_core.h"
21*d83cc019SAndroid Build Coastguard Worker #include "executor.h"
22*d83cc019SAndroid Build Coastguard Worker #include "output_strings.h"
23*d83cc019SAndroid Build Coastguard Worker
24*d83cc019SAndroid Build Coastguard Worker static struct {
25*d83cc019SAndroid Build Coastguard Worker int *fds;
26*d83cc019SAndroid Build Coastguard Worker size_t num_dogs;
27*d83cc019SAndroid Build Coastguard Worker } watchdogs;
28*d83cc019SAndroid Build Coastguard Worker
__close_watchdog(int fd)29*d83cc019SAndroid Build Coastguard Worker static void __close_watchdog(int fd)
30*d83cc019SAndroid Build Coastguard Worker {
31*d83cc019SAndroid Build Coastguard Worker ssize_t ret = write(fd, "V", 1);
32*d83cc019SAndroid Build Coastguard Worker
33*d83cc019SAndroid Build Coastguard Worker if (ret == -1)
34*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Failed to stop a watchdog: %s\n",
35*d83cc019SAndroid Build Coastguard Worker strerror(errno));
36*d83cc019SAndroid Build Coastguard Worker
37*d83cc019SAndroid Build Coastguard Worker close(fd);
38*d83cc019SAndroid Build Coastguard Worker }
39*d83cc019SAndroid Build Coastguard Worker
close_watchdogs(struct settings * settings)40*d83cc019SAndroid Build Coastguard Worker static void close_watchdogs(struct settings *settings)
41*d83cc019SAndroid Build Coastguard Worker {
42*d83cc019SAndroid Build Coastguard Worker size_t i;
43*d83cc019SAndroid Build Coastguard Worker
44*d83cc019SAndroid Build Coastguard Worker if (settings && settings->log_level >= LOG_LEVEL_VERBOSE)
45*d83cc019SAndroid Build Coastguard Worker printf("Closing watchdogs\n");
46*d83cc019SAndroid Build Coastguard Worker
47*d83cc019SAndroid Build Coastguard Worker if (settings == NULL && watchdogs.num_dogs != 0)
48*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Closing watchdogs from exit handler!\n");
49*d83cc019SAndroid Build Coastguard Worker
50*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < watchdogs.num_dogs; i++) {
51*d83cc019SAndroid Build Coastguard Worker __close_watchdog(watchdogs.fds[i]);
52*d83cc019SAndroid Build Coastguard Worker }
53*d83cc019SAndroid Build Coastguard Worker
54*d83cc019SAndroid Build Coastguard Worker free(watchdogs.fds);
55*d83cc019SAndroid Build Coastguard Worker watchdogs.num_dogs = 0;
56*d83cc019SAndroid Build Coastguard Worker watchdogs.fds = NULL;
57*d83cc019SAndroid Build Coastguard Worker }
58*d83cc019SAndroid Build Coastguard Worker
close_watchdogs_atexit(void)59*d83cc019SAndroid Build Coastguard Worker static void close_watchdogs_atexit(void)
60*d83cc019SAndroid Build Coastguard Worker {
61*d83cc019SAndroid Build Coastguard Worker close_watchdogs(NULL);
62*d83cc019SAndroid Build Coastguard Worker }
63*d83cc019SAndroid Build Coastguard Worker
init_watchdogs(struct settings * settings)64*d83cc019SAndroid Build Coastguard Worker static void init_watchdogs(struct settings *settings)
65*d83cc019SAndroid Build Coastguard Worker {
66*d83cc019SAndroid Build Coastguard Worker int i;
67*d83cc019SAndroid Build Coastguard Worker char name[32];
68*d83cc019SAndroid Build Coastguard Worker int fd;
69*d83cc019SAndroid Build Coastguard Worker
70*d83cc019SAndroid Build Coastguard Worker memset(&watchdogs, 0, sizeof(watchdogs));
71*d83cc019SAndroid Build Coastguard Worker
72*d83cc019SAndroid Build Coastguard Worker if (!settings->use_watchdog || settings->inactivity_timeout <= 0)
73*d83cc019SAndroid Build Coastguard Worker return;
74*d83cc019SAndroid Build Coastguard Worker
75*d83cc019SAndroid Build Coastguard Worker if (settings->log_level >= LOG_LEVEL_VERBOSE) {
76*d83cc019SAndroid Build Coastguard Worker printf("Initializing watchdogs\n");
77*d83cc019SAndroid Build Coastguard Worker }
78*d83cc019SAndroid Build Coastguard Worker
79*d83cc019SAndroid Build Coastguard Worker atexit(close_watchdogs_atexit);
80*d83cc019SAndroid Build Coastguard Worker
81*d83cc019SAndroid Build Coastguard Worker for (i = 0; ; i++) {
82*d83cc019SAndroid Build Coastguard Worker snprintf(name, sizeof(name), "/dev/watchdog%d", i);
83*d83cc019SAndroid Build Coastguard Worker if ((fd = open(name, O_RDWR | O_CLOEXEC)) < 0)
84*d83cc019SAndroid Build Coastguard Worker break;
85*d83cc019SAndroid Build Coastguard Worker
86*d83cc019SAndroid Build Coastguard Worker watchdogs.num_dogs++;
87*d83cc019SAndroid Build Coastguard Worker watchdogs.fds = realloc(watchdogs.fds, watchdogs.num_dogs * sizeof(int));
88*d83cc019SAndroid Build Coastguard Worker watchdogs.fds[i] = fd;
89*d83cc019SAndroid Build Coastguard Worker
90*d83cc019SAndroid Build Coastguard Worker if (settings->log_level >= LOG_LEVEL_VERBOSE)
91*d83cc019SAndroid Build Coastguard Worker printf(" %s\n", name);
92*d83cc019SAndroid Build Coastguard Worker }
93*d83cc019SAndroid Build Coastguard Worker }
94*d83cc019SAndroid Build Coastguard Worker
watchdogs_set_timeout(int timeout)95*d83cc019SAndroid Build Coastguard Worker static int watchdogs_set_timeout(int timeout)
96*d83cc019SAndroid Build Coastguard Worker {
97*d83cc019SAndroid Build Coastguard Worker size_t i;
98*d83cc019SAndroid Build Coastguard Worker int orig_timeout = timeout;
99*d83cc019SAndroid Build Coastguard Worker
100*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < watchdogs.num_dogs; i++) {
101*d83cc019SAndroid Build Coastguard Worker if (ioctl(watchdogs.fds[i], WDIOC_SETTIMEOUT, &timeout)) {
102*d83cc019SAndroid Build Coastguard Worker __close_watchdog(watchdogs.fds[i]);
103*d83cc019SAndroid Build Coastguard Worker watchdogs.fds[i] = -1;
104*d83cc019SAndroid Build Coastguard Worker continue;
105*d83cc019SAndroid Build Coastguard Worker }
106*d83cc019SAndroid Build Coastguard Worker
107*d83cc019SAndroid Build Coastguard Worker if (timeout < orig_timeout) {
108*d83cc019SAndroid Build Coastguard Worker /*
109*d83cc019SAndroid Build Coastguard Worker * Timeout of this caliber refused. We want to
110*d83cc019SAndroid Build Coastguard Worker * use the same timeout for all devices.
111*d83cc019SAndroid Build Coastguard Worker */
112*d83cc019SAndroid Build Coastguard Worker return watchdogs_set_timeout(timeout);
113*d83cc019SAndroid Build Coastguard Worker }
114*d83cc019SAndroid Build Coastguard Worker }
115*d83cc019SAndroid Build Coastguard Worker
116*d83cc019SAndroid Build Coastguard Worker return timeout;
117*d83cc019SAndroid Build Coastguard Worker }
118*d83cc019SAndroid Build Coastguard Worker
ping_watchdogs(void)119*d83cc019SAndroid Build Coastguard Worker static void ping_watchdogs(void)
120*d83cc019SAndroid Build Coastguard Worker {
121*d83cc019SAndroid Build Coastguard Worker size_t i;
122*d83cc019SAndroid Build Coastguard Worker int ret;
123*d83cc019SAndroid Build Coastguard Worker
124*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < watchdogs.num_dogs; i++) {
125*d83cc019SAndroid Build Coastguard Worker ret = ioctl(watchdogs.fds[i], WDIOC_KEEPALIVE, NULL);
126*d83cc019SAndroid Build Coastguard Worker
127*d83cc019SAndroid Build Coastguard Worker if (ret == -1)
128*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Failed to ping a watchdog: %s\n",
129*d83cc019SAndroid Build Coastguard Worker strerror(errno));
130*d83cc019SAndroid Build Coastguard Worker }
131*d83cc019SAndroid Build Coastguard Worker }
132*d83cc019SAndroid Build Coastguard Worker
handle_lockdep(void)133*d83cc019SAndroid Build Coastguard Worker static char *handle_lockdep(void)
134*d83cc019SAndroid Build Coastguard Worker {
135*d83cc019SAndroid Build Coastguard Worker const char *header = "Lockdep not active\n\n/proc/lockdep_stats contents:\n";
136*d83cc019SAndroid Build Coastguard Worker int fd = open("/proc/lockdep_stats", O_RDONLY);
137*d83cc019SAndroid Build Coastguard Worker const char *debug_locks_line = " debug_locks:";
138*d83cc019SAndroid Build Coastguard Worker char buf[4096], *p;
139*d83cc019SAndroid Build Coastguard Worker ssize_t bufsize = 0;
140*d83cc019SAndroid Build Coastguard Worker int val;
141*d83cc019SAndroid Build Coastguard Worker
142*d83cc019SAndroid Build Coastguard Worker if (fd < 0)
143*d83cc019SAndroid Build Coastguard Worker return NULL;
144*d83cc019SAndroid Build Coastguard Worker
145*d83cc019SAndroid Build Coastguard Worker strcpy(buf, header);
146*d83cc019SAndroid Build Coastguard Worker
147*d83cc019SAndroid Build Coastguard Worker if ((bufsize = read(fd, buf + strlen(header), sizeof(buf) - strlen(header) - 1)) < 0)
148*d83cc019SAndroid Build Coastguard Worker return NULL;
149*d83cc019SAndroid Build Coastguard Worker bufsize += strlen(header);
150*d83cc019SAndroid Build Coastguard Worker buf[bufsize] = '\0';
151*d83cc019SAndroid Build Coastguard Worker close(fd);
152*d83cc019SAndroid Build Coastguard Worker
153*d83cc019SAndroid Build Coastguard Worker if ((p = strstr(buf, debug_locks_line)) != NULL &&
154*d83cc019SAndroid Build Coastguard Worker sscanf(p + strlen(debug_locks_line), "%d", &val) == 1 &&
155*d83cc019SAndroid Build Coastguard Worker val != 1) {
156*d83cc019SAndroid Build Coastguard Worker return strdup(buf);
157*d83cc019SAndroid Build Coastguard Worker }
158*d83cc019SAndroid Build Coastguard Worker
159*d83cc019SAndroid Build Coastguard Worker return NULL;
160*d83cc019SAndroid Build Coastguard Worker }
161*d83cc019SAndroid Build Coastguard Worker
162*d83cc019SAndroid Build Coastguard Worker /* see Linux's include/linux/kernel.h */
163*d83cc019SAndroid Build Coastguard Worker static const struct {
164*d83cc019SAndroid Build Coastguard Worker unsigned long bit;
165*d83cc019SAndroid Build Coastguard Worker const char *explanation;
166*d83cc019SAndroid Build Coastguard Worker } abort_taints[] = {
167*d83cc019SAndroid Build Coastguard Worker {(1 << 5), "TAINT_BAD_PAGE: Bad page reference or an unexpected page flags."},
168*d83cc019SAndroid Build Coastguard Worker {(1 << 7), "TAINT_DIE: Kernel has died - BUG/OOPS."},
169*d83cc019SAndroid Build Coastguard Worker {(1 << 9), "TAINT_WARN: WARN_ON has happened."},
170*d83cc019SAndroid Build Coastguard Worker {0, 0}};
171*d83cc019SAndroid Build Coastguard Worker
tainted(unsigned long * taints)172*d83cc019SAndroid Build Coastguard Worker static unsigned long tainted(unsigned long *taints)
173*d83cc019SAndroid Build Coastguard Worker {
174*d83cc019SAndroid Build Coastguard Worker FILE *f;
175*d83cc019SAndroid Build Coastguard Worker unsigned long bad_taints = 0;
176*d83cc019SAndroid Build Coastguard Worker
177*d83cc019SAndroid Build Coastguard Worker for (typeof(*abort_taints) *taint = abort_taints; taint->bit; taint++)
178*d83cc019SAndroid Build Coastguard Worker bad_taints |= taint->bit;
179*d83cc019SAndroid Build Coastguard Worker
180*d83cc019SAndroid Build Coastguard Worker *taints = 0;
181*d83cc019SAndroid Build Coastguard Worker
182*d83cc019SAndroid Build Coastguard Worker f = fopen("/proc/sys/kernel/tainted", "r");
183*d83cc019SAndroid Build Coastguard Worker if (f) {
184*d83cc019SAndroid Build Coastguard Worker fscanf(f, "%lu", taints);
185*d83cc019SAndroid Build Coastguard Worker fclose(f);
186*d83cc019SAndroid Build Coastguard Worker }
187*d83cc019SAndroid Build Coastguard Worker
188*d83cc019SAndroid Build Coastguard Worker return *taints & bad_taints;
189*d83cc019SAndroid Build Coastguard Worker }
190*d83cc019SAndroid Build Coastguard Worker
handle_taint(void)191*d83cc019SAndroid Build Coastguard Worker static char *handle_taint(void)
192*d83cc019SAndroid Build Coastguard Worker {
193*d83cc019SAndroid Build Coastguard Worker unsigned long taints;
194*d83cc019SAndroid Build Coastguard Worker char *reason;
195*d83cc019SAndroid Build Coastguard Worker
196*d83cc019SAndroid Build Coastguard Worker if (!tainted(&taints))
197*d83cc019SAndroid Build Coastguard Worker return NULL;
198*d83cc019SAndroid Build Coastguard Worker
199*d83cc019SAndroid Build Coastguard Worker asprintf(&reason, "Kernel badly tainted (%#lx) (check dmesg for details):\n",
200*d83cc019SAndroid Build Coastguard Worker taints);
201*d83cc019SAndroid Build Coastguard Worker
202*d83cc019SAndroid Build Coastguard Worker for (typeof(*abort_taints) *taint = abort_taints; taint->bit; taint++) {
203*d83cc019SAndroid Build Coastguard Worker if (taint->bit & taints) {
204*d83cc019SAndroid Build Coastguard Worker char *old_reason = reason;
205*d83cc019SAndroid Build Coastguard Worker asprintf(&reason, "%s\t(%#lx) %s\n",
206*d83cc019SAndroid Build Coastguard Worker old_reason,
207*d83cc019SAndroid Build Coastguard Worker taint->bit,
208*d83cc019SAndroid Build Coastguard Worker taint->explanation);
209*d83cc019SAndroid Build Coastguard Worker free(old_reason);
210*d83cc019SAndroid Build Coastguard Worker }
211*d83cc019SAndroid Build Coastguard Worker }
212*d83cc019SAndroid Build Coastguard Worker
213*d83cc019SAndroid Build Coastguard Worker return reason;
214*d83cc019SAndroid Build Coastguard Worker }
215*d83cc019SAndroid Build Coastguard Worker
216*d83cc019SAndroid Build Coastguard Worker static const struct {
217*d83cc019SAndroid Build Coastguard Worker int condition;
218*d83cc019SAndroid Build Coastguard Worker char *(*handler)(void);
219*d83cc019SAndroid Build Coastguard Worker } abort_handlers[] = {
220*d83cc019SAndroid Build Coastguard Worker { ABORT_LOCKDEP, handle_lockdep },
221*d83cc019SAndroid Build Coastguard Worker { ABORT_TAINT, handle_taint },
222*d83cc019SAndroid Build Coastguard Worker { 0, 0 },
223*d83cc019SAndroid Build Coastguard Worker };
224*d83cc019SAndroid Build Coastguard Worker
need_to_abort(const struct settings * settings)225*d83cc019SAndroid Build Coastguard Worker static char *need_to_abort(const struct settings* settings)
226*d83cc019SAndroid Build Coastguard Worker {
227*d83cc019SAndroid Build Coastguard Worker typeof(*abort_handlers) *it;
228*d83cc019SAndroid Build Coastguard Worker
229*d83cc019SAndroid Build Coastguard Worker for (it = abort_handlers; it->condition; it++) {
230*d83cc019SAndroid Build Coastguard Worker char *abort;
231*d83cc019SAndroid Build Coastguard Worker
232*d83cc019SAndroid Build Coastguard Worker if (!(settings->abort_mask & it->condition))
233*d83cc019SAndroid Build Coastguard Worker continue;
234*d83cc019SAndroid Build Coastguard Worker
235*d83cc019SAndroid Build Coastguard Worker abort = it->handler();
236*d83cc019SAndroid Build Coastguard Worker if (!abort)
237*d83cc019SAndroid Build Coastguard Worker continue;
238*d83cc019SAndroid Build Coastguard Worker
239*d83cc019SAndroid Build Coastguard Worker if (settings->log_level >= LOG_LEVEL_NORMAL)
240*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Aborting: %s\n", abort);
241*d83cc019SAndroid Build Coastguard Worker
242*d83cc019SAndroid Build Coastguard Worker return abort;
243*d83cc019SAndroid Build Coastguard Worker }
244*d83cc019SAndroid Build Coastguard Worker
245*d83cc019SAndroid Build Coastguard Worker return NULL;
246*d83cc019SAndroid Build Coastguard Worker }
247*d83cc019SAndroid Build Coastguard Worker
prune_subtest(struct job_list_entry * entry,char * subtest)248*d83cc019SAndroid Build Coastguard Worker static void prune_subtest(struct job_list_entry *entry, char *subtest)
249*d83cc019SAndroid Build Coastguard Worker {
250*d83cc019SAndroid Build Coastguard Worker char *excl;
251*d83cc019SAndroid Build Coastguard Worker
252*d83cc019SAndroid Build Coastguard Worker /*
253*d83cc019SAndroid Build Coastguard Worker * Subtest pruning is done by adding exclusion strings to the
254*d83cc019SAndroid Build Coastguard Worker * subtest list. The last matching item on the subtest
255*d83cc019SAndroid Build Coastguard Worker * selection command line flag decides whether to run a
256*d83cc019SAndroid Build Coastguard Worker * subtest, see igt_core.c for details. If the list is empty,
257*d83cc019SAndroid Build Coastguard Worker * the expected subtest set is unknown, so we need to add '*'
258*d83cc019SAndroid Build Coastguard Worker * first so we can start excluding.
259*d83cc019SAndroid Build Coastguard Worker */
260*d83cc019SAndroid Build Coastguard Worker
261*d83cc019SAndroid Build Coastguard Worker if (entry->subtest_count == 0) {
262*d83cc019SAndroid Build Coastguard Worker entry->subtest_count++;
263*d83cc019SAndroid Build Coastguard Worker entry->subtests = realloc(entry->subtests, entry->subtest_count * sizeof(*entry->subtests));
264*d83cc019SAndroid Build Coastguard Worker entry->subtests[0] = strdup("*");
265*d83cc019SAndroid Build Coastguard Worker }
266*d83cc019SAndroid Build Coastguard Worker
267*d83cc019SAndroid Build Coastguard Worker excl = malloc(strlen(subtest) + 2);
268*d83cc019SAndroid Build Coastguard Worker excl[0] = '!';
269*d83cc019SAndroid Build Coastguard Worker strcpy(excl + 1, subtest);
270*d83cc019SAndroid Build Coastguard Worker
271*d83cc019SAndroid Build Coastguard Worker entry->subtest_count++;
272*d83cc019SAndroid Build Coastguard Worker entry->subtests = realloc(entry->subtests, entry->subtest_count * sizeof(*entry->subtests));
273*d83cc019SAndroid Build Coastguard Worker entry->subtests[entry->subtest_count - 1] = excl;
274*d83cc019SAndroid Build Coastguard Worker }
275*d83cc019SAndroid Build Coastguard Worker
prune_from_journal(struct job_list_entry * entry,int fd)276*d83cc019SAndroid Build Coastguard Worker static bool prune_from_journal(struct job_list_entry *entry, int fd)
277*d83cc019SAndroid Build Coastguard Worker {
278*d83cc019SAndroid Build Coastguard Worker char *subtest;
279*d83cc019SAndroid Build Coastguard Worker FILE *f;
280*d83cc019SAndroid Build Coastguard Worker size_t pruned = 0;
281*d83cc019SAndroid Build Coastguard Worker size_t old_count = entry->subtest_count;
282*d83cc019SAndroid Build Coastguard Worker
283*d83cc019SAndroid Build Coastguard Worker /*
284*d83cc019SAndroid Build Coastguard Worker * Each journal line is a subtest that has been started, or
285*d83cc019SAndroid Build Coastguard Worker * the line 'exit:$exitcode (time)', or 'timeout:$exitcode (time)'.
286*d83cc019SAndroid Build Coastguard Worker */
287*d83cc019SAndroid Build Coastguard Worker
288*d83cc019SAndroid Build Coastguard Worker f = fdopen(fd, "r");
289*d83cc019SAndroid Build Coastguard Worker if (!f)
290*d83cc019SAndroid Build Coastguard Worker return false;
291*d83cc019SAndroid Build Coastguard Worker
292*d83cc019SAndroid Build Coastguard Worker while (fscanf(f, "%ms", &subtest) == 1) {
293*d83cc019SAndroid Build Coastguard Worker if (!strncmp(subtest, EXECUTOR_EXIT, strlen(EXECUTOR_EXIT))) {
294*d83cc019SAndroid Build Coastguard Worker /* Fully done. Mark that by making the binary name invalid. */
295*d83cc019SAndroid Build Coastguard Worker fscanf(f, " (%*fs)");
296*d83cc019SAndroid Build Coastguard Worker entry->binary[0] = '\0';
297*d83cc019SAndroid Build Coastguard Worker free(subtest);
298*d83cc019SAndroid Build Coastguard Worker continue;
299*d83cc019SAndroid Build Coastguard Worker }
300*d83cc019SAndroid Build Coastguard Worker
301*d83cc019SAndroid Build Coastguard Worker if (!strncmp(subtest, EXECUTOR_TIMEOUT, strlen(EXECUTOR_TIMEOUT))) {
302*d83cc019SAndroid Build Coastguard Worker fscanf(f, " (%*fs)");
303*d83cc019SAndroid Build Coastguard Worker free(subtest);
304*d83cc019SAndroid Build Coastguard Worker continue;
305*d83cc019SAndroid Build Coastguard Worker }
306*d83cc019SAndroid Build Coastguard Worker
307*d83cc019SAndroid Build Coastguard Worker prune_subtest(entry, subtest);
308*d83cc019SAndroid Build Coastguard Worker
309*d83cc019SAndroid Build Coastguard Worker free(subtest);
310*d83cc019SAndroid Build Coastguard Worker pruned++;
311*d83cc019SAndroid Build Coastguard Worker }
312*d83cc019SAndroid Build Coastguard Worker
313*d83cc019SAndroid Build Coastguard Worker fclose(f);
314*d83cc019SAndroid Build Coastguard Worker
315*d83cc019SAndroid Build Coastguard Worker /*
316*d83cc019SAndroid Build Coastguard Worker * If we know the subtests we originally wanted to run, check
317*d83cc019SAndroid Build Coastguard Worker * if we got an equal amount already.
318*d83cc019SAndroid Build Coastguard Worker */
319*d83cc019SAndroid Build Coastguard Worker if (old_count > 0 && pruned >= old_count)
320*d83cc019SAndroid Build Coastguard Worker entry->binary[0] = '\0';
321*d83cc019SAndroid Build Coastguard Worker
322*d83cc019SAndroid Build Coastguard Worker return pruned > 0;
323*d83cc019SAndroid Build Coastguard Worker }
324*d83cc019SAndroid Build Coastguard Worker
325*d83cc019SAndroid Build Coastguard Worker static const char *filenames[_F_LAST] = {
326*d83cc019SAndroid Build Coastguard Worker [_F_JOURNAL] = "journal.txt",
327*d83cc019SAndroid Build Coastguard Worker [_F_OUT] = "out.txt",
328*d83cc019SAndroid Build Coastguard Worker [_F_ERR] = "err.txt",
329*d83cc019SAndroid Build Coastguard Worker [_F_DMESG] = "dmesg.txt",
330*d83cc019SAndroid Build Coastguard Worker };
331*d83cc019SAndroid Build Coastguard Worker
open_at_end(int dirfd,const char * name)332*d83cc019SAndroid Build Coastguard Worker static int open_at_end(int dirfd, const char *name)
333*d83cc019SAndroid Build Coastguard Worker {
334*d83cc019SAndroid Build Coastguard Worker int fd = openat(dirfd, name, O_RDWR | O_CREAT | O_CLOEXEC, 0666);
335*d83cc019SAndroid Build Coastguard Worker char last;
336*d83cc019SAndroid Build Coastguard Worker
337*d83cc019SAndroid Build Coastguard Worker if (fd >= 0) {
338*d83cc019SAndroid Build Coastguard Worker if (lseek(fd, -1, SEEK_END) >= 0 &&
339*d83cc019SAndroid Build Coastguard Worker read(fd, &last, 1) == 1 &&
340*d83cc019SAndroid Build Coastguard Worker last != '\n') {
341*d83cc019SAndroid Build Coastguard Worker write(fd, "\n", 1);
342*d83cc019SAndroid Build Coastguard Worker }
343*d83cc019SAndroid Build Coastguard Worker lseek(fd, 0, SEEK_END);
344*d83cc019SAndroid Build Coastguard Worker }
345*d83cc019SAndroid Build Coastguard Worker
346*d83cc019SAndroid Build Coastguard Worker return fd;
347*d83cc019SAndroid Build Coastguard Worker }
348*d83cc019SAndroid Build Coastguard Worker
open_for_reading(int dirfd,const char * name)349*d83cc019SAndroid Build Coastguard Worker static int open_for_reading(int dirfd, const char *name)
350*d83cc019SAndroid Build Coastguard Worker {
351*d83cc019SAndroid Build Coastguard Worker return openat(dirfd, name, O_RDONLY);
352*d83cc019SAndroid Build Coastguard Worker }
353*d83cc019SAndroid Build Coastguard Worker
open_output_files(int dirfd,int * fds,bool write)354*d83cc019SAndroid Build Coastguard Worker bool open_output_files(int dirfd, int *fds, bool write)
355*d83cc019SAndroid Build Coastguard Worker {
356*d83cc019SAndroid Build Coastguard Worker int i;
357*d83cc019SAndroid Build Coastguard Worker int (*openfunc)(int, const char*) = write ? open_at_end : open_for_reading;
358*d83cc019SAndroid Build Coastguard Worker
359*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < _F_LAST; i++) {
360*d83cc019SAndroid Build Coastguard Worker if ((fds[i] = openfunc(dirfd, filenames[i])) < 0) {
361*d83cc019SAndroid Build Coastguard Worker while (--i >= 0)
362*d83cc019SAndroid Build Coastguard Worker close(fds[i]);
363*d83cc019SAndroid Build Coastguard Worker return false;
364*d83cc019SAndroid Build Coastguard Worker }
365*d83cc019SAndroid Build Coastguard Worker }
366*d83cc019SAndroid Build Coastguard Worker
367*d83cc019SAndroid Build Coastguard Worker return true;
368*d83cc019SAndroid Build Coastguard Worker }
369*d83cc019SAndroid Build Coastguard Worker
close_outputs(int * fds)370*d83cc019SAndroid Build Coastguard Worker void close_outputs(int *fds)
371*d83cc019SAndroid Build Coastguard Worker {
372*d83cc019SAndroid Build Coastguard Worker int i;
373*d83cc019SAndroid Build Coastguard Worker
374*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < _F_LAST; i++) {
375*d83cc019SAndroid Build Coastguard Worker close(fds[i]);
376*d83cc019SAndroid Build Coastguard Worker }
377*d83cc019SAndroid Build Coastguard Worker }
378*d83cc019SAndroid Build Coastguard Worker
dump_dmesg(int kmsgfd,int outfd)379*d83cc019SAndroid Build Coastguard Worker static void dump_dmesg(int kmsgfd, int outfd)
380*d83cc019SAndroid Build Coastguard Worker {
381*d83cc019SAndroid Build Coastguard Worker /*
382*d83cc019SAndroid Build Coastguard Worker * Write kernel messages to the log file until we reach
383*d83cc019SAndroid Build Coastguard Worker * 'now'. Unfortunately, /dev/kmsg doesn't support seeking to
384*d83cc019SAndroid Build Coastguard Worker * -1 from SEEK_END so we need to use a second fd to read a
385*d83cc019SAndroid Build Coastguard Worker * message to match against, or stop when we reach EAGAIN.
386*d83cc019SAndroid Build Coastguard Worker */
387*d83cc019SAndroid Build Coastguard Worker
388*d83cc019SAndroid Build Coastguard Worker int comparefd = open("/dev/kmsg", O_RDONLY | O_NONBLOCK);
389*d83cc019SAndroid Build Coastguard Worker unsigned flags;
390*d83cc019SAndroid Build Coastguard Worker unsigned long long seq, cmpseq, usec;
391*d83cc019SAndroid Build Coastguard Worker char cont;
392*d83cc019SAndroid Build Coastguard Worker char buf[2048];
393*d83cc019SAndroid Build Coastguard Worker ssize_t r;
394*d83cc019SAndroid Build Coastguard Worker
395*d83cc019SAndroid Build Coastguard Worker if (comparefd < 0)
396*d83cc019SAndroid Build Coastguard Worker return;
397*d83cc019SAndroid Build Coastguard Worker lseek(comparefd, 0, SEEK_END);
398*d83cc019SAndroid Build Coastguard Worker
399*d83cc019SAndroid Build Coastguard Worker if (fcntl(kmsgfd, F_SETFL, O_NONBLOCK)) {
400*d83cc019SAndroid Build Coastguard Worker close(comparefd);
401*d83cc019SAndroid Build Coastguard Worker return;
402*d83cc019SAndroid Build Coastguard Worker }
403*d83cc019SAndroid Build Coastguard Worker
404*d83cc019SAndroid Build Coastguard Worker while (1) {
405*d83cc019SAndroid Build Coastguard Worker if (comparefd >= 0) {
406*d83cc019SAndroid Build Coastguard Worker r = read(comparefd, buf, sizeof(buf) - 1);
407*d83cc019SAndroid Build Coastguard Worker if (r < 0) {
408*d83cc019SAndroid Build Coastguard Worker if (errno != EAGAIN && errno != EPIPE) {
409*d83cc019SAndroid Build Coastguard Worker close(comparefd);
410*d83cc019SAndroid Build Coastguard Worker return;
411*d83cc019SAndroid Build Coastguard Worker }
412*d83cc019SAndroid Build Coastguard Worker } else {
413*d83cc019SAndroid Build Coastguard Worker buf[r] = '\0';
414*d83cc019SAndroid Build Coastguard Worker if (sscanf(buf, "%u,%llu,%llu,%c;",
415*d83cc019SAndroid Build Coastguard Worker &flags, &cmpseq, &usec, &cont) == 4) {
416*d83cc019SAndroid Build Coastguard Worker /* Reading comparison record done. */
417*d83cc019SAndroid Build Coastguard Worker close(comparefd);
418*d83cc019SAndroid Build Coastguard Worker comparefd = -1;
419*d83cc019SAndroid Build Coastguard Worker }
420*d83cc019SAndroid Build Coastguard Worker }
421*d83cc019SAndroid Build Coastguard Worker }
422*d83cc019SAndroid Build Coastguard Worker
423*d83cc019SAndroid Build Coastguard Worker r = read(kmsgfd, buf, sizeof(buf));
424*d83cc019SAndroid Build Coastguard Worker if (r <= 0) {
425*d83cc019SAndroid Build Coastguard Worker if (errno == EPIPE)
426*d83cc019SAndroid Build Coastguard Worker continue;
427*d83cc019SAndroid Build Coastguard Worker
428*d83cc019SAndroid Build Coastguard Worker /*
429*d83cc019SAndroid Build Coastguard Worker * If EAGAIN, we're done. If some other error,
430*d83cc019SAndroid Build Coastguard Worker * we can't do anything anyway.
431*d83cc019SAndroid Build Coastguard Worker */
432*d83cc019SAndroid Build Coastguard Worker close(comparefd);
433*d83cc019SAndroid Build Coastguard Worker return;
434*d83cc019SAndroid Build Coastguard Worker }
435*d83cc019SAndroid Build Coastguard Worker
436*d83cc019SAndroid Build Coastguard Worker write(outfd, buf, r);
437*d83cc019SAndroid Build Coastguard Worker
438*d83cc019SAndroid Build Coastguard Worker if (comparefd < 0 && sscanf(buf, "%u,%llu,%llu,%c;",
439*d83cc019SAndroid Build Coastguard Worker &flags, &seq, &usec, &cont) == 4) {
440*d83cc019SAndroid Build Coastguard Worker /*
441*d83cc019SAndroid Build Coastguard Worker * Comparison record has been read, compare
442*d83cc019SAndroid Build Coastguard Worker * the sequence number to see if we have read
443*d83cc019SAndroid Build Coastguard Worker * enough.
444*d83cc019SAndroid Build Coastguard Worker */
445*d83cc019SAndroid Build Coastguard Worker if (seq >= cmpseq)
446*d83cc019SAndroid Build Coastguard Worker return;
447*d83cc019SAndroid Build Coastguard Worker }
448*d83cc019SAndroid Build Coastguard Worker }
449*d83cc019SAndroid Build Coastguard Worker }
450*d83cc019SAndroid Build Coastguard Worker
kill_child(int sig,pid_t child)451*d83cc019SAndroid Build Coastguard Worker static bool kill_child(int sig, pid_t child)
452*d83cc019SAndroid Build Coastguard Worker {
453*d83cc019SAndroid Build Coastguard Worker /*
454*d83cc019SAndroid Build Coastguard Worker * Send the signal to the child directly, and to the child's
455*d83cc019SAndroid Build Coastguard Worker * process group.
456*d83cc019SAndroid Build Coastguard Worker */
457*d83cc019SAndroid Build Coastguard Worker kill(-child, sig);
458*d83cc019SAndroid Build Coastguard Worker if (kill(child, sig) && errno == ESRCH) {
459*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Child process does not exist. This shouldn't happen.\n");
460*d83cc019SAndroid Build Coastguard Worker return false;
461*d83cc019SAndroid Build Coastguard Worker }
462*d83cc019SAndroid Build Coastguard Worker
463*d83cc019SAndroid Build Coastguard Worker return true;
464*d83cc019SAndroid Build Coastguard Worker }
465*d83cc019SAndroid Build Coastguard Worker
466*d83cc019SAndroid Build Coastguard Worker /*
467*d83cc019SAndroid Build Coastguard Worker * Returns:
468*d83cc019SAndroid Build Coastguard Worker * =0 - Success
469*d83cc019SAndroid Build Coastguard Worker * <0 - Failure executing
470*d83cc019SAndroid Build Coastguard Worker * >0 - Timeout happened, need to recreate from journal
471*d83cc019SAndroid Build Coastguard Worker */
monitor_output(pid_t child,int outfd,int errfd,int kmsgfd,int sigfd,int * outputs,double * time_spent,struct settings * settings)472*d83cc019SAndroid Build Coastguard Worker static int monitor_output(pid_t child,
473*d83cc019SAndroid Build Coastguard Worker int outfd, int errfd, int kmsgfd, int sigfd,
474*d83cc019SAndroid Build Coastguard Worker int *outputs,
475*d83cc019SAndroid Build Coastguard Worker double *time_spent,
476*d83cc019SAndroid Build Coastguard Worker struct settings *settings)
477*d83cc019SAndroid Build Coastguard Worker {
478*d83cc019SAndroid Build Coastguard Worker fd_set set;
479*d83cc019SAndroid Build Coastguard Worker char buf[2048];
480*d83cc019SAndroid Build Coastguard Worker char *outbuf = NULL;
481*d83cc019SAndroid Build Coastguard Worker size_t outbufsize = 0;
482*d83cc019SAndroid Build Coastguard Worker char current_subtest[256] = {};
483*d83cc019SAndroid Build Coastguard Worker struct signalfd_siginfo siginfo;
484*d83cc019SAndroid Build Coastguard Worker ssize_t s;
485*d83cc019SAndroid Build Coastguard Worker int n, status;
486*d83cc019SAndroid Build Coastguard Worker int nfds = outfd;
487*d83cc019SAndroid Build Coastguard Worker int timeout = settings->inactivity_timeout;
488*d83cc019SAndroid Build Coastguard Worker int timeout_intervals = 1, intervals_left;
489*d83cc019SAndroid Build Coastguard Worker int wd_extra = 10;
490*d83cc019SAndroid Build Coastguard Worker int killed = 0; /* 0 if not killed, signal number otherwise */
491*d83cc019SAndroid Build Coastguard Worker struct timespec time_beg, time_end;
492*d83cc019SAndroid Build Coastguard Worker unsigned long taints = 0;
493*d83cc019SAndroid Build Coastguard Worker bool aborting = false;
494*d83cc019SAndroid Build Coastguard Worker
495*d83cc019SAndroid Build Coastguard Worker igt_gettime(&time_beg);
496*d83cc019SAndroid Build Coastguard Worker
497*d83cc019SAndroid Build Coastguard Worker if (errfd > nfds)
498*d83cc019SAndroid Build Coastguard Worker nfds = errfd;
499*d83cc019SAndroid Build Coastguard Worker if (kmsgfd > nfds)
500*d83cc019SAndroid Build Coastguard Worker nfds = kmsgfd;
501*d83cc019SAndroid Build Coastguard Worker if (sigfd > nfds)
502*d83cc019SAndroid Build Coastguard Worker nfds = sigfd;
503*d83cc019SAndroid Build Coastguard Worker nfds++;
504*d83cc019SAndroid Build Coastguard Worker
505*d83cc019SAndroid Build Coastguard Worker if (timeout > 0) {
506*d83cc019SAndroid Build Coastguard Worker /*
507*d83cc019SAndroid Build Coastguard Worker * Use original timeout plus some leeway. If we're still
508*d83cc019SAndroid Build Coastguard Worker * alive, we want to kill the test process instead of cutting
509*d83cc019SAndroid Build Coastguard Worker * power.
510*d83cc019SAndroid Build Coastguard Worker */
511*d83cc019SAndroid Build Coastguard Worker int wd_timeout = watchdogs_set_timeout(timeout + wd_extra);
512*d83cc019SAndroid Build Coastguard Worker
513*d83cc019SAndroid Build Coastguard Worker if (wd_timeout < timeout + wd_extra) {
514*d83cc019SAndroid Build Coastguard Worker /* Watchdog timeout smaller, so ping it more often */
515*d83cc019SAndroid Build Coastguard Worker if (wd_timeout - wd_extra < 0)
516*d83cc019SAndroid Build Coastguard Worker wd_extra = wd_timeout / 2;
517*d83cc019SAndroid Build Coastguard Worker timeout_intervals = timeout / (wd_timeout - wd_extra);
518*d83cc019SAndroid Build Coastguard Worker timeout /= timeout_intervals;
519*d83cc019SAndroid Build Coastguard Worker
520*d83cc019SAndroid Build Coastguard Worker if (settings->log_level >= LOG_LEVEL_VERBOSE) {
521*d83cc019SAndroid Build Coastguard Worker printf("Watchdog doesn't support the timeout we requested (shortened to %d seconds).\n"
522*d83cc019SAndroid Build Coastguard Worker "Using %d intervals of %d seconds.\n",
523*d83cc019SAndroid Build Coastguard Worker wd_timeout, timeout_intervals, timeout);
524*d83cc019SAndroid Build Coastguard Worker }
525*d83cc019SAndroid Build Coastguard Worker }
526*d83cc019SAndroid Build Coastguard Worker }
527*d83cc019SAndroid Build Coastguard Worker
528*d83cc019SAndroid Build Coastguard Worker intervals_left = timeout_intervals;
529*d83cc019SAndroid Build Coastguard Worker
530*d83cc019SAndroid Build Coastguard Worker while (outfd >= 0 || errfd >= 0 || sigfd >= 0) {
531*d83cc019SAndroid Build Coastguard Worker struct timeval tv = { .tv_sec = timeout };
532*d83cc019SAndroid Build Coastguard Worker
533*d83cc019SAndroid Build Coastguard Worker FD_ZERO(&set);
534*d83cc019SAndroid Build Coastguard Worker if (outfd >= 0)
535*d83cc019SAndroid Build Coastguard Worker FD_SET(outfd, &set);
536*d83cc019SAndroid Build Coastguard Worker if (errfd >= 0)
537*d83cc019SAndroid Build Coastguard Worker FD_SET(errfd, &set);
538*d83cc019SAndroid Build Coastguard Worker if (kmsgfd >= 0)
539*d83cc019SAndroid Build Coastguard Worker FD_SET(kmsgfd, &set);
540*d83cc019SAndroid Build Coastguard Worker if (sigfd >= 0)
541*d83cc019SAndroid Build Coastguard Worker FD_SET(sigfd, &set);
542*d83cc019SAndroid Build Coastguard Worker
543*d83cc019SAndroid Build Coastguard Worker n = select(nfds, &set, NULL, NULL, timeout == 0 ? NULL : &tv);
544*d83cc019SAndroid Build Coastguard Worker if (n < 0) {
545*d83cc019SAndroid Build Coastguard Worker /* TODO */
546*d83cc019SAndroid Build Coastguard Worker return -1;
547*d83cc019SAndroid Build Coastguard Worker }
548*d83cc019SAndroid Build Coastguard Worker
549*d83cc019SAndroid Build Coastguard Worker if (n == 0) {
550*d83cc019SAndroid Build Coastguard Worker if (--intervals_left)
551*d83cc019SAndroid Build Coastguard Worker continue;
552*d83cc019SAndroid Build Coastguard Worker
553*d83cc019SAndroid Build Coastguard Worker ping_watchdogs();
554*d83cc019SAndroid Build Coastguard Worker
555*d83cc019SAndroid Build Coastguard Worker switch (killed) {
556*d83cc019SAndroid Build Coastguard Worker case 0:
557*d83cc019SAndroid Build Coastguard Worker if (settings->log_level >= LOG_LEVEL_NORMAL) {
558*d83cc019SAndroid Build Coastguard Worker printf("Timeout. Killing the current test with SIGQUIT.\n");
559*d83cc019SAndroid Build Coastguard Worker fflush(stdout);
560*d83cc019SAndroid Build Coastguard Worker }
561*d83cc019SAndroid Build Coastguard Worker
562*d83cc019SAndroid Build Coastguard Worker killed = SIGQUIT;
563*d83cc019SAndroid Build Coastguard Worker if (!kill_child(killed, child))
564*d83cc019SAndroid Build Coastguard Worker return -1;
565*d83cc019SAndroid Build Coastguard Worker
566*d83cc019SAndroid Build Coastguard Worker /*
567*d83cc019SAndroid Build Coastguard Worker * Now continue the loop and let the
568*d83cc019SAndroid Build Coastguard Worker * dying child be handled normally.
569*d83cc019SAndroid Build Coastguard Worker */
570*d83cc019SAndroid Build Coastguard Worker timeout = 20;
571*d83cc019SAndroid Build Coastguard Worker watchdogs_set_timeout(120);
572*d83cc019SAndroid Build Coastguard Worker intervals_left = timeout_intervals = 1;
573*d83cc019SAndroid Build Coastguard Worker break;
574*d83cc019SAndroid Build Coastguard Worker case SIGQUIT:
575*d83cc019SAndroid Build Coastguard Worker if (settings->log_level >= LOG_LEVEL_NORMAL) {
576*d83cc019SAndroid Build Coastguard Worker printf("Timeout. Killing the current test with SIGKILL.\n");
577*d83cc019SAndroid Build Coastguard Worker fflush(stdout);
578*d83cc019SAndroid Build Coastguard Worker }
579*d83cc019SAndroid Build Coastguard Worker
580*d83cc019SAndroid Build Coastguard Worker killed = SIGKILL;
581*d83cc019SAndroid Build Coastguard Worker if (!kill_child(killed, child))
582*d83cc019SAndroid Build Coastguard Worker return -1;
583*d83cc019SAndroid Build Coastguard Worker
584*d83cc019SAndroid Build Coastguard Worker intervals_left = timeout_intervals = 1;
585*d83cc019SAndroid Build Coastguard Worker break;
586*d83cc019SAndroid Build Coastguard Worker case SIGKILL:
587*d83cc019SAndroid Build Coastguard Worker /*
588*d83cc019SAndroid Build Coastguard Worker * If the child still exists, and the kernel
589*d83cc019SAndroid Build Coastguard Worker * hasn't oopsed, assume it is still making
590*d83cc019SAndroid Build Coastguard Worker * forward progress towards exiting (i.e. still
591*d83cc019SAndroid Build Coastguard Worker * freeing all of its resources).
592*d83cc019SAndroid Build Coastguard Worker */
593*d83cc019SAndroid Build Coastguard Worker if (kill(child, 0) == 0 && !tainted(&taints)) {
594*d83cc019SAndroid Build Coastguard Worker intervals_left = 1;
595*d83cc019SAndroid Build Coastguard Worker break;
596*d83cc019SAndroid Build Coastguard Worker }
597*d83cc019SAndroid Build Coastguard Worker
598*d83cc019SAndroid Build Coastguard Worker /* Nothing that can be done, really. Let's tell the caller we want to abort. */
599*d83cc019SAndroid Build Coastguard Worker if (settings->log_level >= LOG_LEVEL_NORMAL) {
600*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Child refuses to die, tainted %lx. Aborting.\n",
601*d83cc019SAndroid Build Coastguard Worker taints);
602*d83cc019SAndroid Build Coastguard Worker }
603*d83cc019SAndroid Build Coastguard Worker close_watchdogs(settings);
604*d83cc019SAndroid Build Coastguard Worker free(outbuf);
605*d83cc019SAndroid Build Coastguard Worker close(outfd);
606*d83cc019SAndroid Build Coastguard Worker close(errfd);
607*d83cc019SAndroid Build Coastguard Worker close(kmsgfd);
608*d83cc019SAndroid Build Coastguard Worker return -1;
609*d83cc019SAndroid Build Coastguard Worker }
610*d83cc019SAndroid Build Coastguard Worker
611*d83cc019SAndroid Build Coastguard Worker continue;
612*d83cc019SAndroid Build Coastguard Worker }
613*d83cc019SAndroid Build Coastguard Worker
614*d83cc019SAndroid Build Coastguard Worker intervals_left = timeout_intervals;
615*d83cc019SAndroid Build Coastguard Worker ping_watchdogs();
616*d83cc019SAndroid Build Coastguard Worker
617*d83cc019SAndroid Build Coastguard Worker /* TODO: Refactor these handlers to their own functions */
618*d83cc019SAndroid Build Coastguard Worker if (outfd >= 0 && FD_ISSET(outfd, &set)) {
619*d83cc019SAndroid Build Coastguard Worker char *newline;
620*d83cc019SAndroid Build Coastguard Worker
621*d83cc019SAndroid Build Coastguard Worker s = read(outfd, buf, sizeof(buf));
622*d83cc019SAndroid Build Coastguard Worker if (s <= 0) {
623*d83cc019SAndroid Build Coastguard Worker if (s < 0) {
624*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Error reading test's stdout: %s\n",
625*d83cc019SAndroid Build Coastguard Worker strerror(errno));
626*d83cc019SAndroid Build Coastguard Worker }
627*d83cc019SAndroid Build Coastguard Worker
628*d83cc019SAndroid Build Coastguard Worker close(outfd);
629*d83cc019SAndroid Build Coastguard Worker outfd = -1;
630*d83cc019SAndroid Build Coastguard Worker goto out_end;
631*d83cc019SAndroid Build Coastguard Worker }
632*d83cc019SAndroid Build Coastguard Worker
633*d83cc019SAndroid Build Coastguard Worker write(outputs[_F_OUT], buf, s);
634*d83cc019SAndroid Build Coastguard Worker if (settings->sync) {
635*d83cc019SAndroid Build Coastguard Worker fdatasync(outputs[_F_OUT]);
636*d83cc019SAndroid Build Coastguard Worker }
637*d83cc019SAndroid Build Coastguard Worker
638*d83cc019SAndroid Build Coastguard Worker outbuf = realloc(outbuf, outbufsize + s);
639*d83cc019SAndroid Build Coastguard Worker memcpy(outbuf + outbufsize, buf, s);
640*d83cc019SAndroid Build Coastguard Worker outbufsize += s;
641*d83cc019SAndroid Build Coastguard Worker
642*d83cc019SAndroid Build Coastguard Worker while ((newline = memchr(outbuf, '\n', outbufsize)) != NULL) {
643*d83cc019SAndroid Build Coastguard Worker size_t linelen = newline - outbuf + 1;
644*d83cc019SAndroid Build Coastguard Worker
645*d83cc019SAndroid Build Coastguard Worker if (linelen > strlen(STARTING_SUBTEST) &&
646*d83cc019SAndroid Build Coastguard Worker !memcmp(outbuf, STARTING_SUBTEST, strlen(STARTING_SUBTEST))) {
647*d83cc019SAndroid Build Coastguard Worker write(outputs[_F_JOURNAL], outbuf + strlen(STARTING_SUBTEST),
648*d83cc019SAndroid Build Coastguard Worker linelen - strlen(STARTING_SUBTEST));
649*d83cc019SAndroid Build Coastguard Worker memcpy(current_subtest, outbuf + strlen(STARTING_SUBTEST),
650*d83cc019SAndroid Build Coastguard Worker linelen - strlen(STARTING_SUBTEST));
651*d83cc019SAndroid Build Coastguard Worker current_subtest[linelen - strlen(STARTING_SUBTEST)] = '\0';
652*d83cc019SAndroid Build Coastguard Worker
653*d83cc019SAndroid Build Coastguard Worker if (settings->log_level >= LOG_LEVEL_VERBOSE) {
654*d83cc019SAndroid Build Coastguard Worker fwrite(outbuf, 1, linelen, stdout);
655*d83cc019SAndroid Build Coastguard Worker }
656*d83cc019SAndroid Build Coastguard Worker }
657*d83cc019SAndroid Build Coastguard Worker if (linelen > strlen(SUBTEST_RESULT) &&
658*d83cc019SAndroid Build Coastguard Worker !memcmp(outbuf, SUBTEST_RESULT, strlen(SUBTEST_RESULT))) {
659*d83cc019SAndroid Build Coastguard Worker char *delim = memchr(outbuf, ':', linelen);
660*d83cc019SAndroid Build Coastguard Worker
661*d83cc019SAndroid Build Coastguard Worker if (delim != NULL) {
662*d83cc019SAndroid Build Coastguard Worker size_t subtestlen = delim - outbuf - strlen(SUBTEST_RESULT);
663*d83cc019SAndroid Build Coastguard Worker if (memcmp(current_subtest, outbuf + strlen(SUBTEST_RESULT),
664*d83cc019SAndroid Build Coastguard Worker subtestlen)) {
665*d83cc019SAndroid Build Coastguard Worker /* Result for a test that didn't ever start */
666*d83cc019SAndroid Build Coastguard Worker write(outputs[_F_JOURNAL],
667*d83cc019SAndroid Build Coastguard Worker outbuf + strlen(SUBTEST_RESULT),
668*d83cc019SAndroid Build Coastguard Worker subtestlen);
669*d83cc019SAndroid Build Coastguard Worker write(outputs[_F_JOURNAL], "\n", 1);
670*d83cc019SAndroid Build Coastguard Worker if (settings->sync) {
671*d83cc019SAndroid Build Coastguard Worker fdatasync(outputs[_F_JOURNAL]);
672*d83cc019SAndroid Build Coastguard Worker }
673*d83cc019SAndroid Build Coastguard Worker current_subtest[0] = '\0';
674*d83cc019SAndroid Build Coastguard Worker }
675*d83cc019SAndroid Build Coastguard Worker
676*d83cc019SAndroid Build Coastguard Worker if (settings->log_level >= LOG_LEVEL_VERBOSE) {
677*d83cc019SAndroid Build Coastguard Worker fwrite(outbuf, 1, linelen, stdout);
678*d83cc019SAndroid Build Coastguard Worker }
679*d83cc019SAndroid Build Coastguard Worker }
680*d83cc019SAndroid Build Coastguard Worker }
681*d83cc019SAndroid Build Coastguard Worker
682*d83cc019SAndroid Build Coastguard Worker memmove(outbuf, newline + 1, outbufsize - linelen);
683*d83cc019SAndroid Build Coastguard Worker outbufsize -= linelen;
684*d83cc019SAndroid Build Coastguard Worker }
685*d83cc019SAndroid Build Coastguard Worker }
686*d83cc019SAndroid Build Coastguard Worker out_end:
687*d83cc019SAndroid Build Coastguard Worker
688*d83cc019SAndroid Build Coastguard Worker if (errfd >= 0 && FD_ISSET(errfd, &set)) {
689*d83cc019SAndroid Build Coastguard Worker s = read(errfd, buf, sizeof(buf));
690*d83cc019SAndroid Build Coastguard Worker if (s <= 0) {
691*d83cc019SAndroid Build Coastguard Worker if (s < 0) {
692*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Error reading test's stderr: %s\n",
693*d83cc019SAndroid Build Coastguard Worker strerror(errno));
694*d83cc019SAndroid Build Coastguard Worker }
695*d83cc019SAndroid Build Coastguard Worker close(errfd);
696*d83cc019SAndroid Build Coastguard Worker errfd = -1;
697*d83cc019SAndroid Build Coastguard Worker } else {
698*d83cc019SAndroid Build Coastguard Worker write(outputs[_F_ERR], buf, s);
699*d83cc019SAndroid Build Coastguard Worker if (settings->sync) {
700*d83cc019SAndroid Build Coastguard Worker fdatasync(outputs[_F_ERR]);
701*d83cc019SAndroid Build Coastguard Worker }
702*d83cc019SAndroid Build Coastguard Worker }
703*d83cc019SAndroid Build Coastguard Worker }
704*d83cc019SAndroid Build Coastguard Worker
705*d83cc019SAndroid Build Coastguard Worker if (kmsgfd >= 0 && FD_ISSET(kmsgfd, &set)) {
706*d83cc019SAndroid Build Coastguard Worker s = read(kmsgfd, buf, sizeof(buf));
707*d83cc019SAndroid Build Coastguard Worker if (s < 0) {
708*d83cc019SAndroid Build Coastguard Worker if (errno != EPIPE && errno != EINVAL) {
709*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Error reading from kmsg, stopping monitoring: %s\n",
710*d83cc019SAndroid Build Coastguard Worker strerror(errno));
711*d83cc019SAndroid Build Coastguard Worker close(kmsgfd);
712*d83cc019SAndroid Build Coastguard Worker kmsgfd = -1;
713*d83cc019SAndroid Build Coastguard Worker } else if (errno == EINVAL) {
714*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Warning: Buffer too small for kernel log record, record lost.\n");
715*d83cc019SAndroid Build Coastguard Worker }
716*d83cc019SAndroid Build Coastguard Worker } else {
717*d83cc019SAndroid Build Coastguard Worker write(outputs[_F_DMESG], buf, s);
718*d83cc019SAndroid Build Coastguard Worker if (settings->sync) {
719*d83cc019SAndroid Build Coastguard Worker fdatasync(outputs[_F_DMESG]);
720*d83cc019SAndroid Build Coastguard Worker }
721*d83cc019SAndroid Build Coastguard Worker }
722*d83cc019SAndroid Build Coastguard Worker }
723*d83cc019SAndroid Build Coastguard Worker
724*d83cc019SAndroid Build Coastguard Worker if (sigfd >= 0 && FD_ISSET(sigfd, &set)) {
725*d83cc019SAndroid Build Coastguard Worker double time;
726*d83cc019SAndroid Build Coastguard Worker
727*d83cc019SAndroid Build Coastguard Worker s = read(sigfd, &siginfo, sizeof(siginfo));
728*d83cc019SAndroid Build Coastguard Worker if (s < 0) {
729*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Error reading from signalfd: %s\n",
730*d83cc019SAndroid Build Coastguard Worker strerror(errno));
731*d83cc019SAndroid Build Coastguard Worker continue;
732*d83cc019SAndroid Build Coastguard Worker } else if (siginfo.ssi_signo == SIGCHLD) {
733*d83cc019SAndroid Build Coastguard Worker if (child != waitpid(child, &status, WNOHANG)) {
734*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Failed to reap child\n");
735*d83cc019SAndroid Build Coastguard Worker status = 9999;
736*d83cc019SAndroid Build Coastguard Worker } else if (WIFEXITED(status)) {
737*d83cc019SAndroid Build Coastguard Worker status = WEXITSTATUS(status);
738*d83cc019SAndroid Build Coastguard Worker if (status >= 128) {
739*d83cc019SAndroid Build Coastguard Worker status = 128 - status;
740*d83cc019SAndroid Build Coastguard Worker }
741*d83cc019SAndroid Build Coastguard Worker } else if (WIFSIGNALED(status)) {
742*d83cc019SAndroid Build Coastguard Worker status = -WTERMSIG(status);
743*d83cc019SAndroid Build Coastguard Worker } else {
744*d83cc019SAndroid Build Coastguard Worker status = 9999;
745*d83cc019SAndroid Build Coastguard Worker }
746*d83cc019SAndroid Build Coastguard Worker } else {
747*d83cc019SAndroid Build Coastguard Worker /* We're dying, so we're taking them with us */
748*d83cc019SAndroid Build Coastguard Worker if (settings->log_level >= LOG_LEVEL_NORMAL)
749*d83cc019SAndroid Build Coastguard Worker printf("Abort requested via %s, terminating children\n",
750*d83cc019SAndroid Build Coastguard Worker strsignal(siginfo.ssi_signo));
751*d83cc019SAndroid Build Coastguard Worker
752*d83cc019SAndroid Build Coastguard Worker aborting = true;
753*d83cc019SAndroid Build Coastguard Worker timeout = 2;
754*d83cc019SAndroid Build Coastguard Worker killed = SIGQUIT;
755*d83cc019SAndroid Build Coastguard Worker if (!kill_child(killed, child))
756*d83cc019SAndroid Build Coastguard Worker return -1;
757*d83cc019SAndroid Build Coastguard Worker
758*d83cc019SAndroid Build Coastguard Worker continue;
759*d83cc019SAndroid Build Coastguard Worker }
760*d83cc019SAndroid Build Coastguard Worker
761*d83cc019SAndroid Build Coastguard Worker igt_gettime(&time_end);
762*d83cc019SAndroid Build Coastguard Worker
763*d83cc019SAndroid Build Coastguard Worker time = igt_time_elapsed(&time_beg, &time_end);
764*d83cc019SAndroid Build Coastguard Worker if (time < 0.0)
765*d83cc019SAndroid Build Coastguard Worker time = 0.0;
766*d83cc019SAndroid Build Coastguard Worker
767*d83cc019SAndroid Build Coastguard Worker if (!aborting) {
768*d83cc019SAndroid Build Coastguard Worker dprintf(outputs[_F_JOURNAL], "%s%d (%.3fs)\n",
769*d83cc019SAndroid Build Coastguard Worker killed ? EXECUTOR_TIMEOUT : EXECUTOR_EXIT,
770*d83cc019SAndroid Build Coastguard Worker status, time);
771*d83cc019SAndroid Build Coastguard Worker if (settings->sync) {
772*d83cc019SAndroid Build Coastguard Worker fdatasync(outputs[_F_JOURNAL]);
773*d83cc019SAndroid Build Coastguard Worker }
774*d83cc019SAndroid Build Coastguard Worker
775*d83cc019SAndroid Build Coastguard Worker if (time_spent)
776*d83cc019SAndroid Build Coastguard Worker *time_spent = time;
777*d83cc019SAndroid Build Coastguard Worker }
778*d83cc019SAndroid Build Coastguard Worker
779*d83cc019SAndroid Build Coastguard Worker child = 0;
780*d83cc019SAndroid Build Coastguard Worker sigfd = -1; /* we are dying, no signal handling for now */
781*d83cc019SAndroid Build Coastguard Worker }
782*d83cc019SAndroid Build Coastguard Worker }
783*d83cc019SAndroid Build Coastguard Worker
784*d83cc019SAndroid Build Coastguard Worker dump_dmesg(kmsgfd, outputs[_F_DMESG]);
785*d83cc019SAndroid Build Coastguard Worker if (settings->sync)
786*d83cc019SAndroid Build Coastguard Worker fdatasync(outputs[_F_DMESG]);
787*d83cc019SAndroid Build Coastguard Worker
788*d83cc019SAndroid Build Coastguard Worker free(outbuf);
789*d83cc019SAndroid Build Coastguard Worker close(outfd);
790*d83cc019SAndroid Build Coastguard Worker close(errfd);
791*d83cc019SAndroid Build Coastguard Worker close(kmsgfd);
792*d83cc019SAndroid Build Coastguard Worker
793*d83cc019SAndroid Build Coastguard Worker if (aborting)
794*d83cc019SAndroid Build Coastguard Worker return -1;
795*d83cc019SAndroid Build Coastguard Worker
796*d83cc019SAndroid Build Coastguard Worker return killed;
797*d83cc019SAndroid Build Coastguard Worker }
798*d83cc019SAndroid Build Coastguard Worker
799*d83cc019SAndroid Build Coastguard Worker static void __attribute__((noreturn))
execute_test_process(int outfd,int errfd,struct settings * settings,struct job_list_entry * entry)800*d83cc019SAndroid Build Coastguard Worker execute_test_process(int outfd, int errfd,
801*d83cc019SAndroid Build Coastguard Worker struct settings *settings,
802*d83cc019SAndroid Build Coastguard Worker struct job_list_entry *entry)
803*d83cc019SAndroid Build Coastguard Worker {
804*d83cc019SAndroid Build Coastguard Worker char *argv[4] = {};
805*d83cc019SAndroid Build Coastguard Worker size_t rootlen;
806*d83cc019SAndroid Build Coastguard Worker
807*d83cc019SAndroid Build Coastguard Worker dup2(outfd, STDOUT_FILENO);
808*d83cc019SAndroid Build Coastguard Worker dup2(errfd, STDERR_FILENO);
809*d83cc019SAndroid Build Coastguard Worker
810*d83cc019SAndroid Build Coastguard Worker setpgid(0, 0);
811*d83cc019SAndroid Build Coastguard Worker
812*d83cc019SAndroid Build Coastguard Worker rootlen = strlen(settings->test_root);
813*d83cc019SAndroid Build Coastguard Worker argv[0] = malloc(rootlen + strlen(entry->binary) + 2);
814*d83cc019SAndroid Build Coastguard Worker strcpy(argv[0], settings->test_root);
815*d83cc019SAndroid Build Coastguard Worker argv[0][rootlen] = '/';
816*d83cc019SAndroid Build Coastguard Worker strcpy(argv[0] + rootlen + 1, entry->binary);
817*d83cc019SAndroid Build Coastguard Worker
818*d83cc019SAndroid Build Coastguard Worker if (entry->subtest_count) {
819*d83cc019SAndroid Build Coastguard Worker size_t argsize;
820*d83cc019SAndroid Build Coastguard Worker size_t i;
821*d83cc019SAndroid Build Coastguard Worker
822*d83cc019SAndroid Build Coastguard Worker argv[1] = strdup("--run-subtest");
823*d83cc019SAndroid Build Coastguard Worker argsize = strlen(entry->subtests[0]);
824*d83cc019SAndroid Build Coastguard Worker argv[2] = malloc(argsize + 1);
825*d83cc019SAndroid Build Coastguard Worker strcpy(argv[2], entry->subtests[0]);
826*d83cc019SAndroid Build Coastguard Worker
827*d83cc019SAndroid Build Coastguard Worker for (i = 1; i < entry->subtest_count; i++) {
828*d83cc019SAndroid Build Coastguard Worker char *sub = entry->subtests[i];
829*d83cc019SAndroid Build Coastguard Worker size_t sublen = strlen(sub);
830*d83cc019SAndroid Build Coastguard Worker
831*d83cc019SAndroid Build Coastguard Worker argv[2] = realloc(argv[2], argsize + sublen + 2);
832*d83cc019SAndroid Build Coastguard Worker argv[2][argsize] = ',';
833*d83cc019SAndroid Build Coastguard Worker strcpy(argv[2] + argsize + 1, sub);
834*d83cc019SAndroid Build Coastguard Worker argsize += sublen + 1;
835*d83cc019SAndroid Build Coastguard Worker }
836*d83cc019SAndroid Build Coastguard Worker }
837*d83cc019SAndroid Build Coastguard Worker
838*d83cc019SAndroid Build Coastguard Worker execv(argv[0], argv);
839*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Cannot execute %s\n", argv[0]);
840*d83cc019SAndroid Build Coastguard Worker exit(IGT_EXIT_INVALID);
841*d83cc019SAndroid Build Coastguard Worker }
842*d83cc019SAndroid Build Coastguard Worker
digits(size_t num)843*d83cc019SAndroid Build Coastguard Worker static int digits(size_t num)
844*d83cc019SAndroid Build Coastguard Worker {
845*d83cc019SAndroid Build Coastguard Worker int ret = 0;
846*d83cc019SAndroid Build Coastguard Worker while (num) {
847*d83cc019SAndroid Build Coastguard Worker num /= 10;
848*d83cc019SAndroid Build Coastguard Worker ret++;
849*d83cc019SAndroid Build Coastguard Worker }
850*d83cc019SAndroid Build Coastguard Worker
851*d83cc019SAndroid Build Coastguard Worker if (ret == 0) ret++;
852*d83cc019SAndroid Build Coastguard Worker return ret;
853*d83cc019SAndroid Build Coastguard Worker }
854*d83cc019SAndroid Build Coastguard Worker
print_time_left(struct execute_state * state,struct settings * settings)855*d83cc019SAndroid Build Coastguard Worker static void print_time_left(struct execute_state *state,
856*d83cc019SAndroid Build Coastguard Worker struct settings *settings)
857*d83cc019SAndroid Build Coastguard Worker {
858*d83cc019SAndroid Build Coastguard Worker int width;
859*d83cc019SAndroid Build Coastguard Worker
860*d83cc019SAndroid Build Coastguard Worker if (settings->overall_timeout <= 0)
861*d83cc019SAndroid Build Coastguard Worker return;
862*d83cc019SAndroid Build Coastguard Worker
863*d83cc019SAndroid Build Coastguard Worker width = digits(settings->overall_timeout);
864*d83cc019SAndroid Build Coastguard Worker printf("(%*.0fs left) ", width, state->time_left);
865*d83cc019SAndroid Build Coastguard Worker }
866*d83cc019SAndroid Build Coastguard Worker
entry_display_name(struct job_list_entry * entry)867*d83cc019SAndroid Build Coastguard Worker static char *entry_display_name(struct job_list_entry *entry)
868*d83cc019SAndroid Build Coastguard Worker {
869*d83cc019SAndroid Build Coastguard Worker size_t size = strlen(entry->binary) + 1;
870*d83cc019SAndroid Build Coastguard Worker char *ret = malloc(size);
871*d83cc019SAndroid Build Coastguard Worker
872*d83cc019SAndroid Build Coastguard Worker sprintf(ret, "%s", entry->binary);
873*d83cc019SAndroid Build Coastguard Worker
874*d83cc019SAndroid Build Coastguard Worker if (entry->subtest_count > 0) {
875*d83cc019SAndroid Build Coastguard Worker size_t i;
876*d83cc019SAndroid Build Coastguard Worker const char *delim = "";
877*d83cc019SAndroid Build Coastguard Worker
878*d83cc019SAndroid Build Coastguard Worker size += 3; /* strlen(" (") + strlen(")") */
879*d83cc019SAndroid Build Coastguard Worker ret = realloc(ret, size);
880*d83cc019SAndroid Build Coastguard Worker strcat(ret, " (");
881*d83cc019SAndroid Build Coastguard Worker
882*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < entry->subtest_count; i++) {
883*d83cc019SAndroid Build Coastguard Worker size += strlen(delim) + strlen(entry->subtests[i]);
884*d83cc019SAndroid Build Coastguard Worker ret = realloc(ret, size);
885*d83cc019SAndroid Build Coastguard Worker
886*d83cc019SAndroid Build Coastguard Worker strcat(ret, delim);
887*d83cc019SAndroid Build Coastguard Worker strcat(ret, entry->subtests[i]);
888*d83cc019SAndroid Build Coastguard Worker
889*d83cc019SAndroid Build Coastguard Worker delim = ", ";
890*d83cc019SAndroid Build Coastguard Worker }
891*d83cc019SAndroid Build Coastguard Worker /* There's already room for this */
892*d83cc019SAndroid Build Coastguard Worker strcat(ret, ")");
893*d83cc019SAndroid Build Coastguard Worker }
894*d83cc019SAndroid Build Coastguard Worker
895*d83cc019SAndroid Build Coastguard Worker return ret;
896*d83cc019SAndroid Build Coastguard Worker }
897*d83cc019SAndroid Build Coastguard Worker
898*d83cc019SAndroid Build Coastguard Worker /*
899*d83cc019SAndroid Build Coastguard Worker * Returns:
900*d83cc019SAndroid Build Coastguard Worker * =0 - Success
901*d83cc019SAndroid Build Coastguard Worker * <0 - Failure executing
902*d83cc019SAndroid Build Coastguard Worker * >0 - Timeout happened, need to recreate from journal
903*d83cc019SAndroid Build Coastguard Worker */
execute_next_entry(struct execute_state * state,size_t total,double * time_spent,struct settings * settings,struct job_list_entry * entry,int testdirfd,int resdirfd,int sigfd,sigset_t * sigmask)904*d83cc019SAndroid Build Coastguard Worker static int execute_next_entry(struct execute_state *state,
905*d83cc019SAndroid Build Coastguard Worker size_t total,
906*d83cc019SAndroid Build Coastguard Worker double *time_spent,
907*d83cc019SAndroid Build Coastguard Worker struct settings *settings,
908*d83cc019SAndroid Build Coastguard Worker struct job_list_entry *entry,
909*d83cc019SAndroid Build Coastguard Worker int testdirfd, int resdirfd,
910*d83cc019SAndroid Build Coastguard Worker int sigfd, sigset_t *sigmask)
911*d83cc019SAndroid Build Coastguard Worker {
912*d83cc019SAndroid Build Coastguard Worker int dirfd;
913*d83cc019SAndroid Build Coastguard Worker int outputs[_F_LAST];
914*d83cc019SAndroid Build Coastguard Worker int kmsgfd;
915*d83cc019SAndroid Build Coastguard Worker int outpipe[2] = { -1, -1 };
916*d83cc019SAndroid Build Coastguard Worker int errpipe[2] = { -1, -1 };
917*d83cc019SAndroid Build Coastguard Worker int outfd, errfd;
918*d83cc019SAndroid Build Coastguard Worker char name[32];
919*d83cc019SAndroid Build Coastguard Worker pid_t child;
920*d83cc019SAndroid Build Coastguard Worker int result;
921*d83cc019SAndroid Build Coastguard Worker size_t idx = state->next;
922*d83cc019SAndroid Build Coastguard Worker
923*d83cc019SAndroid Build Coastguard Worker snprintf(name, sizeof(name), "%zd", idx);
924*d83cc019SAndroid Build Coastguard Worker mkdirat(resdirfd, name, 0777);
925*d83cc019SAndroid Build Coastguard Worker if ((dirfd = openat(resdirfd, name, O_DIRECTORY | O_RDONLY | O_CLOEXEC)) < 0) {
926*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Error accessing individual test result directory\n");
927*d83cc019SAndroid Build Coastguard Worker return -1;
928*d83cc019SAndroid Build Coastguard Worker }
929*d83cc019SAndroid Build Coastguard Worker
930*d83cc019SAndroid Build Coastguard Worker if (!open_output_files(dirfd, outputs, true)) {
931*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Error opening output files\n");
932*d83cc019SAndroid Build Coastguard Worker result = -1;
933*d83cc019SAndroid Build Coastguard Worker goto out_dirfd;
934*d83cc019SAndroid Build Coastguard Worker }
935*d83cc019SAndroid Build Coastguard Worker
936*d83cc019SAndroid Build Coastguard Worker if (settings->sync) {
937*d83cc019SAndroid Build Coastguard Worker fsync(dirfd);
938*d83cc019SAndroid Build Coastguard Worker fsync(resdirfd);
939*d83cc019SAndroid Build Coastguard Worker }
940*d83cc019SAndroid Build Coastguard Worker
941*d83cc019SAndroid Build Coastguard Worker if (pipe(outpipe) || pipe(errpipe)) {
942*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Error creating pipes: %s\n", strerror(errno));
943*d83cc019SAndroid Build Coastguard Worker result = -1;
944*d83cc019SAndroid Build Coastguard Worker goto out_pipe;
945*d83cc019SAndroid Build Coastguard Worker }
946*d83cc019SAndroid Build Coastguard Worker
947*d83cc019SAndroid Build Coastguard Worker if ((kmsgfd = open("/dev/kmsg", O_RDONLY | O_CLOEXEC)) < 0) {
948*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Warning: Cannot open /dev/kmsg\n");
949*d83cc019SAndroid Build Coastguard Worker } else {
950*d83cc019SAndroid Build Coastguard Worker /* TODO: Checking of abort conditions in pre-execute dmesg */
951*d83cc019SAndroid Build Coastguard Worker lseek(kmsgfd, 0, SEEK_END);
952*d83cc019SAndroid Build Coastguard Worker }
953*d83cc019SAndroid Build Coastguard Worker
954*d83cc019SAndroid Build Coastguard Worker
955*d83cc019SAndroid Build Coastguard Worker if (settings->log_level >= LOG_LEVEL_NORMAL) {
956*d83cc019SAndroid Build Coastguard Worker char *displayname;
957*d83cc019SAndroid Build Coastguard Worker int width = digits(total);
958*d83cc019SAndroid Build Coastguard Worker printf("[%0*zd/%0*zd] ", width, idx + 1, width, total);
959*d83cc019SAndroid Build Coastguard Worker
960*d83cc019SAndroid Build Coastguard Worker print_time_left(state, settings);
961*d83cc019SAndroid Build Coastguard Worker
962*d83cc019SAndroid Build Coastguard Worker displayname = entry_display_name(entry);
963*d83cc019SAndroid Build Coastguard Worker printf("%s", displayname);
964*d83cc019SAndroid Build Coastguard Worker free(displayname);
965*d83cc019SAndroid Build Coastguard Worker
966*d83cc019SAndroid Build Coastguard Worker printf("\n");
967*d83cc019SAndroid Build Coastguard Worker }
968*d83cc019SAndroid Build Coastguard Worker
969*d83cc019SAndroid Build Coastguard Worker /*
970*d83cc019SAndroid Build Coastguard Worker * Flush outputs before forking so our (buffered) output won't
971*d83cc019SAndroid Build Coastguard Worker * end up in the test outputs.
972*d83cc019SAndroid Build Coastguard Worker */
973*d83cc019SAndroid Build Coastguard Worker fflush(stdout);
974*d83cc019SAndroid Build Coastguard Worker fflush(stderr);
975*d83cc019SAndroid Build Coastguard Worker
976*d83cc019SAndroid Build Coastguard Worker child = fork();
977*d83cc019SAndroid Build Coastguard Worker if (child < 0) {
978*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Failed to fork: %s\n", strerror(errno));
979*d83cc019SAndroid Build Coastguard Worker result = -1;
980*d83cc019SAndroid Build Coastguard Worker goto out_kmsgfd;
981*d83cc019SAndroid Build Coastguard Worker } else if (child == 0) {
982*d83cc019SAndroid Build Coastguard Worker outfd = outpipe[1];
983*d83cc019SAndroid Build Coastguard Worker errfd = errpipe[1];
984*d83cc019SAndroid Build Coastguard Worker close(outpipe[0]);
985*d83cc019SAndroid Build Coastguard Worker close(errpipe[0]);
986*d83cc019SAndroid Build Coastguard Worker
987*d83cc019SAndroid Build Coastguard Worker sigprocmask(SIG_UNBLOCK, sigmask, NULL);
988*d83cc019SAndroid Build Coastguard Worker
989*d83cc019SAndroid Build Coastguard Worker setenv("IGT_SENTINEL_ON_STDERR", "1", 1);
990*d83cc019SAndroid Build Coastguard Worker
991*d83cc019SAndroid Build Coastguard Worker execute_test_process(outfd, errfd, settings, entry);
992*d83cc019SAndroid Build Coastguard Worker /* unreachable */
993*d83cc019SAndroid Build Coastguard Worker }
994*d83cc019SAndroid Build Coastguard Worker
995*d83cc019SAndroid Build Coastguard Worker outfd = outpipe[0];
996*d83cc019SAndroid Build Coastguard Worker errfd = errpipe[0];
997*d83cc019SAndroid Build Coastguard Worker close(outpipe[1]);
998*d83cc019SAndroid Build Coastguard Worker close(errpipe[1]);
999*d83cc019SAndroid Build Coastguard Worker outpipe[1] = errpipe[1] = -1;
1000*d83cc019SAndroid Build Coastguard Worker
1001*d83cc019SAndroid Build Coastguard Worker result = monitor_output(child, outfd, errfd, kmsgfd, sigfd,
1002*d83cc019SAndroid Build Coastguard Worker outputs, time_spent, settings);
1003*d83cc019SAndroid Build Coastguard Worker
1004*d83cc019SAndroid Build Coastguard Worker out_kmsgfd:
1005*d83cc019SAndroid Build Coastguard Worker close(kmsgfd);
1006*d83cc019SAndroid Build Coastguard Worker out_pipe:
1007*d83cc019SAndroid Build Coastguard Worker close_outputs(outputs);
1008*d83cc019SAndroid Build Coastguard Worker close(outpipe[0]);
1009*d83cc019SAndroid Build Coastguard Worker close(outpipe[1]);
1010*d83cc019SAndroid Build Coastguard Worker close(errpipe[0]);
1011*d83cc019SAndroid Build Coastguard Worker close(errpipe[1]);
1012*d83cc019SAndroid Build Coastguard Worker close_outputs(outputs);
1013*d83cc019SAndroid Build Coastguard Worker out_dirfd:
1014*d83cc019SAndroid Build Coastguard Worker close(dirfd);
1015*d83cc019SAndroid Build Coastguard Worker
1016*d83cc019SAndroid Build Coastguard Worker return result;
1017*d83cc019SAndroid Build Coastguard Worker }
1018*d83cc019SAndroid Build Coastguard Worker
remove_file(int dirfd,const char * name)1019*d83cc019SAndroid Build Coastguard Worker static int remove_file(int dirfd, const char *name)
1020*d83cc019SAndroid Build Coastguard Worker {
1021*d83cc019SAndroid Build Coastguard Worker return unlinkat(dirfd, name, 0) && errno != ENOENT;
1022*d83cc019SAndroid Build Coastguard Worker }
1023*d83cc019SAndroid Build Coastguard Worker
clear_test_result_directory(int dirfd)1024*d83cc019SAndroid Build Coastguard Worker static bool clear_test_result_directory(int dirfd)
1025*d83cc019SAndroid Build Coastguard Worker {
1026*d83cc019SAndroid Build Coastguard Worker int i;
1027*d83cc019SAndroid Build Coastguard Worker
1028*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < _F_LAST; i++) {
1029*d83cc019SAndroid Build Coastguard Worker if (remove_file(dirfd, filenames[i])) {
1030*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Error deleting %s from test result directory: %s\n",
1031*d83cc019SAndroid Build Coastguard Worker filenames[i],
1032*d83cc019SAndroid Build Coastguard Worker strerror(errno));
1033*d83cc019SAndroid Build Coastguard Worker return false;
1034*d83cc019SAndroid Build Coastguard Worker }
1035*d83cc019SAndroid Build Coastguard Worker }
1036*d83cc019SAndroid Build Coastguard Worker
1037*d83cc019SAndroid Build Coastguard Worker return true;
1038*d83cc019SAndroid Build Coastguard Worker }
1039*d83cc019SAndroid Build Coastguard Worker
clear_old_results(char * path)1040*d83cc019SAndroid Build Coastguard Worker static bool clear_old_results(char *path)
1041*d83cc019SAndroid Build Coastguard Worker {
1042*d83cc019SAndroid Build Coastguard Worker int dirfd;
1043*d83cc019SAndroid Build Coastguard Worker size_t i;
1044*d83cc019SAndroid Build Coastguard Worker
1045*d83cc019SAndroid Build Coastguard Worker if ((dirfd = open(path, O_DIRECTORY | O_RDONLY)) < 0) {
1046*d83cc019SAndroid Build Coastguard Worker if (errno == ENOENT) {
1047*d83cc019SAndroid Build Coastguard Worker /* Successfully cleared if it doesn't even exist */
1048*d83cc019SAndroid Build Coastguard Worker return true;
1049*d83cc019SAndroid Build Coastguard Worker }
1050*d83cc019SAndroid Build Coastguard Worker
1051*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Error clearing old results: %s\n", strerror(errno));
1052*d83cc019SAndroid Build Coastguard Worker return false;
1053*d83cc019SAndroid Build Coastguard Worker }
1054*d83cc019SAndroid Build Coastguard Worker
1055*d83cc019SAndroid Build Coastguard Worker if (remove_file(dirfd, "uname.txt") ||
1056*d83cc019SAndroid Build Coastguard Worker remove_file(dirfd, "starttime.txt") ||
1057*d83cc019SAndroid Build Coastguard Worker remove_file(dirfd, "endtime.txt") ||
1058*d83cc019SAndroid Build Coastguard Worker remove_file(dirfd, "aborted.txt")) {
1059*d83cc019SAndroid Build Coastguard Worker close(dirfd);
1060*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Error clearing old results: %s\n", strerror(errno));
1061*d83cc019SAndroid Build Coastguard Worker return false;
1062*d83cc019SAndroid Build Coastguard Worker }
1063*d83cc019SAndroid Build Coastguard Worker
1064*d83cc019SAndroid Build Coastguard Worker for (i = 0; true; i++) {
1065*d83cc019SAndroid Build Coastguard Worker char name[32];
1066*d83cc019SAndroid Build Coastguard Worker int resdirfd;
1067*d83cc019SAndroid Build Coastguard Worker
1068*d83cc019SAndroid Build Coastguard Worker snprintf(name, sizeof(name), "%zd", i);
1069*d83cc019SAndroid Build Coastguard Worker if ((resdirfd = openat(dirfd, name, O_DIRECTORY | O_RDONLY)) < 0)
1070*d83cc019SAndroid Build Coastguard Worker break;
1071*d83cc019SAndroid Build Coastguard Worker
1072*d83cc019SAndroid Build Coastguard Worker if (!clear_test_result_directory(resdirfd)) {
1073*d83cc019SAndroid Build Coastguard Worker close(resdirfd);
1074*d83cc019SAndroid Build Coastguard Worker close(dirfd);
1075*d83cc019SAndroid Build Coastguard Worker return false;
1076*d83cc019SAndroid Build Coastguard Worker }
1077*d83cc019SAndroid Build Coastguard Worker close(resdirfd);
1078*d83cc019SAndroid Build Coastguard Worker if (unlinkat(dirfd, name, AT_REMOVEDIR)) {
1079*d83cc019SAndroid Build Coastguard Worker fprintf(stderr,
1080*d83cc019SAndroid Build Coastguard Worker "Warning: Result directory %s contains extra files\n",
1081*d83cc019SAndroid Build Coastguard Worker name);
1082*d83cc019SAndroid Build Coastguard Worker }
1083*d83cc019SAndroid Build Coastguard Worker }
1084*d83cc019SAndroid Build Coastguard Worker
1085*d83cc019SAndroid Build Coastguard Worker close(dirfd);
1086*d83cc019SAndroid Build Coastguard Worker
1087*d83cc019SAndroid Build Coastguard Worker return true;
1088*d83cc019SAndroid Build Coastguard Worker }
1089*d83cc019SAndroid Build Coastguard Worker
timeofday_double(void)1090*d83cc019SAndroid Build Coastguard Worker static double timeofday_double(void)
1091*d83cc019SAndroid Build Coastguard Worker {
1092*d83cc019SAndroid Build Coastguard Worker struct timeval tv;
1093*d83cc019SAndroid Build Coastguard Worker
1094*d83cc019SAndroid Build Coastguard Worker if (!gettimeofday(&tv, NULL))
1095*d83cc019SAndroid Build Coastguard Worker return tv.tv_sec + tv.tv_usec / 1000000.0;
1096*d83cc019SAndroid Build Coastguard Worker return 0.0;
1097*d83cc019SAndroid Build Coastguard Worker }
1098*d83cc019SAndroid Build Coastguard Worker
init_time_left(struct execute_state * state,struct settings * settings)1099*d83cc019SAndroid Build Coastguard Worker static void init_time_left(struct execute_state *state,
1100*d83cc019SAndroid Build Coastguard Worker struct settings *settings)
1101*d83cc019SAndroid Build Coastguard Worker {
1102*d83cc019SAndroid Build Coastguard Worker if (settings->overall_timeout <= 0)
1103*d83cc019SAndroid Build Coastguard Worker state->time_left = -1;
1104*d83cc019SAndroid Build Coastguard Worker else
1105*d83cc019SAndroid Build Coastguard Worker state->time_left = settings->overall_timeout;
1106*d83cc019SAndroid Build Coastguard Worker }
1107*d83cc019SAndroid Build Coastguard Worker
initialize_execute_state_from_resume(int dirfd,struct execute_state * state,struct settings * settings,struct job_list * list)1108*d83cc019SAndroid Build Coastguard Worker bool initialize_execute_state_from_resume(int dirfd,
1109*d83cc019SAndroid Build Coastguard Worker struct execute_state *state,
1110*d83cc019SAndroid Build Coastguard Worker struct settings *settings,
1111*d83cc019SAndroid Build Coastguard Worker struct job_list *list)
1112*d83cc019SAndroid Build Coastguard Worker {
1113*d83cc019SAndroid Build Coastguard Worker struct job_list_entry *entry;
1114*d83cc019SAndroid Build Coastguard Worker int resdirfd, fd, i;
1115*d83cc019SAndroid Build Coastguard Worker
1116*d83cc019SAndroid Build Coastguard Worker free_settings(settings);
1117*d83cc019SAndroid Build Coastguard Worker free_job_list(list);
1118*d83cc019SAndroid Build Coastguard Worker memset(state, 0, sizeof(*state));
1119*d83cc019SAndroid Build Coastguard Worker state->resuming = true;
1120*d83cc019SAndroid Build Coastguard Worker
1121*d83cc019SAndroid Build Coastguard Worker if (!read_settings_from_dir(settings, dirfd) ||
1122*d83cc019SAndroid Build Coastguard Worker !read_job_list(list, dirfd)) {
1123*d83cc019SAndroid Build Coastguard Worker close(dirfd);
1124*d83cc019SAndroid Build Coastguard Worker return false;
1125*d83cc019SAndroid Build Coastguard Worker }
1126*d83cc019SAndroid Build Coastguard Worker
1127*d83cc019SAndroid Build Coastguard Worker init_time_left(state, settings);
1128*d83cc019SAndroid Build Coastguard Worker
1129*d83cc019SAndroid Build Coastguard Worker for (i = list->size; i >= 0; i--) {
1130*d83cc019SAndroid Build Coastguard Worker char name[32];
1131*d83cc019SAndroid Build Coastguard Worker
1132*d83cc019SAndroid Build Coastguard Worker snprintf(name, sizeof(name), "%d", i);
1133*d83cc019SAndroid Build Coastguard Worker if ((resdirfd = openat(dirfd, name, O_DIRECTORY | O_RDONLY)) >= 0)
1134*d83cc019SAndroid Build Coastguard Worker break;
1135*d83cc019SAndroid Build Coastguard Worker }
1136*d83cc019SAndroid Build Coastguard Worker
1137*d83cc019SAndroid Build Coastguard Worker if (i < 0)
1138*d83cc019SAndroid Build Coastguard Worker /* Nothing has been executed yet, state is fine as is */
1139*d83cc019SAndroid Build Coastguard Worker goto success;
1140*d83cc019SAndroid Build Coastguard Worker
1141*d83cc019SAndroid Build Coastguard Worker entry = &list->entries[i];
1142*d83cc019SAndroid Build Coastguard Worker state->next = i;
1143*d83cc019SAndroid Build Coastguard Worker if ((fd = openat(resdirfd, filenames[_F_JOURNAL], O_RDONLY)) >= 0) {
1144*d83cc019SAndroid Build Coastguard Worker if (!prune_from_journal(entry, fd)) {
1145*d83cc019SAndroid Build Coastguard Worker /*
1146*d83cc019SAndroid Build Coastguard Worker * The test does not have subtests, or
1147*d83cc019SAndroid Build Coastguard Worker * incompleted before the first subtest
1148*d83cc019SAndroid Build Coastguard Worker * began. Either way, not suitable to
1149*d83cc019SAndroid Build Coastguard Worker * re-run.
1150*d83cc019SAndroid Build Coastguard Worker */
1151*d83cc019SAndroid Build Coastguard Worker state->next = i + 1;
1152*d83cc019SAndroid Build Coastguard Worker } else if (entry->binary[0] == '\0') {
1153*d83cc019SAndroid Build Coastguard Worker /* This test is fully completed */
1154*d83cc019SAndroid Build Coastguard Worker state->next = i + 1;
1155*d83cc019SAndroid Build Coastguard Worker }
1156*d83cc019SAndroid Build Coastguard Worker
1157*d83cc019SAndroid Build Coastguard Worker close(fd);
1158*d83cc019SAndroid Build Coastguard Worker }
1159*d83cc019SAndroid Build Coastguard Worker
1160*d83cc019SAndroid Build Coastguard Worker success:
1161*d83cc019SAndroid Build Coastguard Worker close(resdirfd);
1162*d83cc019SAndroid Build Coastguard Worker close(dirfd);
1163*d83cc019SAndroid Build Coastguard Worker
1164*d83cc019SAndroid Build Coastguard Worker return true;
1165*d83cc019SAndroid Build Coastguard Worker }
1166*d83cc019SAndroid Build Coastguard Worker
initialize_execute_state(struct execute_state * state,struct settings * settings,struct job_list * job_list)1167*d83cc019SAndroid Build Coastguard Worker bool initialize_execute_state(struct execute_state *state,
1168*d83cc019SAndroid Build Coastguard Worker struct settings *settings,
1169*d83cc019SAndroid Build Coastguard Worker struct job_list *job_list)
1170*d83cc019SAndroid Build Coastguard Worker {
1171*d83cc019SAndroid Build Coastguard Worker memset(state, 0, sizeof(*state));
1172*d83cc019SAndroid Build Coastguard Worker
1173*d83cc019SAndroid Build Coastguard Worker if (!validate_settings(settings))
1174*d83cc019SAndroid Build Coastguard Worker return false;
1175*d83cc019SAndroid Build Coastguard Worker
1176*d83cc019SAndroid Build Coastguard Worker if (!serialize_settings(settings) ||
1177*d83cc019SAndroid Build Coastguard Worker !serialize_job_list(job_list, settings))
1178*d83cc019SAndroid Build Coastguard Worker return false;
1179*d83cc019SAndroid Build Coastguard Worker
1180*d83cc019SAndroid Build Coastguard Worker if (settings->overwrite &&
1181*d83cc019SAndroid Build Coastguard Worker !clear_old_results(settings->results_path))
1182*d83cc019SAndroid Build Coastguard Worker return false;
1183*d83cc019SAndroid Build Coastguard Worker
1184*d83cc019SAndroid Build Coastguard Worker init_time_left(state, settings);
1185*d83cc019SAndroid Build Coastguard Worker
1186*d83cc019SAndroid Build Coastguard Worker state->dry = settings->dry_run;
1187*d83cc019SAndroid Build Coastguard Worker
1188*d83cc019SAndroid Build Coastguard Worker return true;
1189*d83cc019SAndroid Build Coastguard Worker }
1190*d83cc019SAndroid Build Coastguard Worker
reduce_time_left(struct settings * settings,struct execute_state * state,double time_spent)1191*d83cc019SAndroid Build Coastguard Worker static void reduce_time_left(struct settings *settings,
1192*d83cc019SAndroid Build Coastguard Worker struct execute_state *state,
1193*d83cc019SAndroid Build Coastguard Worker double time_spent)
1194*d83cc019SAndroid Build Coastguard Worker {
1195*d83cc019SAndroid Build Coastguard Worker if (state->time_left < 0)
1196*d83cc019SAndroid Build Coastguard Worker return;
1197*d83cc019SAndroid Build Coastguard Worker
1198*d83cc019SAndroid Build Coastguard Worker if (time_spent > state->time_left)
1199*d83cc019SAndroid Build Coastguard Worker state->time_left = 0.0;
1200*d83cc019SAndroid Build Coastguard Worker else
1201*d83cc019SAndroid Build Coastguard Worker state->time_left -= time_spent;
1202*d83cc019SAndroid Build Coastguard Worker }
1203*d83cc019SAndroid Build Coastguard Worker
overall_timeout_exceeded(struct execute_state * state)1204*d83cc019SAndroid Build Coastguard Worker static bool overall_timeout_exceeded(struct execute_state *state)
1205*d83cc019SAndroid Build Coastguard Worker {
1206*d83cc019SAndroid Build Coastguard Worker return state->time_left == 0.0;
1207*d83cc019SAndroid Build Coastguard Worker }
1208*d83cc019SAndroid Build Coastguard Worker
write_abort_file(int resdirfd,const char * reason,const char * testbefore,const char * testafter)1209*d83cc019SAndroid Build Coastguard Worker static void write_abort_file(int resdirfd,
1210*d83cc019SAndroid Build Coastguard Worker const char *reason,
1211*d83cc019SAndroid Build Coastguard Worker const char *testbefore,
1212*d83cc019SAndroid Build Coastguard Worker const char *testafter)
1213*d83cc019SAndroid Build Coastguard Worker {
1214*d83cc019SAndroid Build Coastguard Worker int abortfd;
1215*d83cc019SAndroid Build Coastguard Worker
1216*d83cc019SAndroid Build Coastguard Worker if ((abortfd = openat(resdirfd, "aborted.txt", O_CREAT | O_WRONLY | O_EXCL, 0666)) >= 0) {
1217*d83cc019SAndroid Build Coastguard Worker /*
1218*d83cc019SAndroid Build Coastguard Worker * Ignore failure to open, there's
1219*d83cc019SAndroid Build Coastguard Worker * already an abort probably (if this
1220*d83cc019SAndroid Build Coastguard Worker * is a resume)
1221*d83cc019SAndroid Build Coastguard Worker */
1222*d83cc019SAndroid Build Coastguard Worker dprintf(abortfd, "Aborting.\n");
1223*d83cc019SAndroid Build Coastguard Worker dprintf(abortfd, "Previous test: %s\n", testbefore);
1224*d83cc019SAndroid Build Coastguard Worker dprintf(abortfd, "Next test: %s\n\n", testafter);
1225*d83cc019SAndroid Build Coastguard Worker write(abortfd, reason, strlen(reason));
1226*d83cc019SAndroid Build Coastguard Worker close(abortfd);
1227*d83cc019SAndroid Build Coastguard Worker }
1228*d83cc019SAndroid Build Coastguard Worker }
1229*d83cc019SAndroid Build Coastguard Worker
oom_immortal(void)1230*d83cc019SAndroid Build Coastguard Worker static void oom_immortal(void)
1231*d83cc019SAndroid Build Coastguard Worker {
1232*d83cc019SAndroid Build Coastguard Worker int fd;
1233*d83cc019SAndroid Build Coastguard Worker const char never_kill[] = "-1000";
1234*d83cc019SAndroid Build Coastguard Worker
1235*d83cc019SAndroid Build Coastguard Worker fd = open("/proc/self/oom_score_adj", O_WRONLY);
1236*d83cc019SAndroid Build Coastguard Worker if (fd < 0) {
1237*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Warning: Cannot adjust oom score.\n");
1238*d83cc019SAndroid Build Coastguard Worker return;
1239*d83cc019SAndroid Build Coastguard Worker }
1240*d83cc019SAndroid Build Coastguard Worker if (write(fd, never_kill, sizeof(never_kill)) != sizeof(never_kill))
1241*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Warning: Adjusting oom score failed.\n");
1242*d83cc019SAndroid Build Coastguard Worker
1243*d83cc019SAndroid Build Coastguard Worker close(fd);
1244*d83cc019SAndroid Build Coastguard Worker }
1245*d83cc019SAndroid Build Coastguard Worker
should_die_because_signal(int sigfd)1246*d83cc019SAndroid Build Coastguard Worker static bool should_die_because_signal(int sigfd)
1247*d83cc019SAndroid Build Coastguard Worker {
1248*d83cc019SAndroid Build Coastguard Worker struct signalfd_siginfo siginfo;
1249*d83cc019SAndroid Build Coastguard Worker int ret;
1250*d83cc019SAndroid Build Coastguard Worker struct pollfd sigpoll = { .fd = sigfd, .events = POLLIN | POLLRDBAND };
1251*d83cc019SAndroid Build Coastguard Worker
1252*d83cc019SAndroid Build Coastguard Worker ret = poll(&sigpoll, 1, 0);
1253*d83cc019SAndroid Build Coastguard Worker
1254*d83cc019SAndroid Build Coastguard Worker if (ret != 0) {
1255*d83cc019SAndroid Build Coastguard Worker if (ret == -1) {
1256*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Poll on signalfd failed with %s\n", strerror(errno));
1257*d83cc019SAndroid Build Coastguard Worker return true; /* something is wrong, let's die */
1258*d83cc019SAndroid Build Coastguard Worker }
1259*d83cc019SAndroid Build Coastguard Worker
1260*d83cc019SAndroid Build Coastguard Worker ret = read(sigfd, &siginfo, sizeof(siginfo));
1261*d83cc019SAndroid Build Coastguard Worker
1262*d83cc019SAndroid Build Coastguard Worker if (ret == -1) {
1263*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Error reading from signalfd: %s\n", strerror(errno));
1264*d83cc019SAndroid Build Coastguard Worker return false; /* we may want to retry later */
1265*d83cc019SAndroid Build Coastguard Worker }
1266*d83cc019SAndroid Build Coastguard Worker
1267*d83cc019SAndroid Build Coastguard Worker if (siginfo.ssi_signo == SIGCHLD) {
1268*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Runner got stray SIGCHLD while not executing any tests.\n");
1269*d83cc019SAndroid Build Coastguard Worker } else {
1270*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Runner is being killed by %s\n",
1271*d83cc019SAndroid Build Coastguard Worker strsignal(siginfo.ssi_signo));
1272*d83cc019SAndroid Build Coastguard Worker return true;
1273*d83cc019SAndroid Build Coastguard Worker }
1274*d83cc019SAndroid Build Coastguard Worker
1275*d83cc019SAndroid Build Coastguard Worker }
1276*d83cc019SAndroid Build Coastguard Worker
1277*d83cc019SAndroid Build Coastguard Worker return false;
1278*d83cc019SAndroid Build Coastguard Worker }
1279*d83cc019SAndroid Build Coastguard Worker
execute(struct execute_state * state,struct settings * settings,struct job_list * job_list)1280*d83cc019SAndroid Build Coastguard Worker bool execute(struct execute_state *state,
1281*d83cc019SAndroid Build Coastguard Worker struct settings *settings,
1282*d83cc019SAndroid Build Coastguard Worker struct job_list *job_list)
1283*d83cc019SAndroid Build Coastguard Worker {
1284*d83cc019SAndroid Build Coastguard Worker struct utsname unamebuf;
1285*d83cc019SAndroid Build Coastguard Worker int resdirfd, testdirfd, unamefd, timefd;
1286*d83cc019SAndroid Build Coastguard Worker sigset_t sigmask;
1287*d83cc019SAndroid Build Coastguard Worker int sigfd;
1288*d83cc019SAndroid Build Coastguard Worker double time_spent = 0.0;
1289*d83cc019SAndroid Build Coastguard Worker bool status = true;
1290*d83cc019SAndroid Build Coastguard Worker
1291*d83cc019SAndroid Build Coastguard Worker if (state->dry) {
1292*d83cc019SAndroid Build Coastguard Worker printf("Dry run, not executing. Invoke igt_resume if you want to execute.\n");
1293*d83cc019SAndroid Build Coastguard Worker return true;
1294*d83cc019SAndroid Build Coastguard Worker }
1295*d83cc019SAndroid Build Coastguard Worker
1296*d83cc019SAndroid Build Coastguard Worker if ((resdirfd = open(settings->results_path, O_DIRECTORY | O_RDONLY)) < 0) {
1297*d83cc019SAndroid Build Coastguard Worker /* Initialize state should have done this */
1298*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Error: Failure opening results path %s\n",
1299*d83cc019SAndroid Build Coastguard Worker settings->results_path);
1300*d83cc019SAndroid Build Coastguard Worker return false;
1301*d83cc019SAndroid Build Coastguard Worker }
1302*d83cc019SAndroid Build Coastguard Worker
1303*d83cc019SAndroid Build Coastguard Worker if ((testdirfd = open(settings->test_root, O_DIRECTORY | O_RDONLY)) < 0) {
1304*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Error: Failure opening test root %s\n",
1305*d83cc019SAndroid Build Coastguard Worker settings->test_root);
1306*d83cc019SAndroid Build Coastguard Worker close(resdirfd);
1307*d83cc019SAndroid Build Coastguard Worker return false;
1308*d83cc019SAndroid Build Coastguard Worker }
1309*d83cc019SAndroid Build Coastguard Worker
1310*d83cc019SAndroid Build Coastguard Worker /* TODO: On resume, don't rewrite, verify that content matches current instead */
1311*d83cc019SAndroid Build Coastguard Worker if ((unamefd = openat(resdirfd, "uname.txt", O_CREAT | O_WRONLY | O_TRUNC, 0666)) < 0) {
1312*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Error: Failure opening uname.txt: %s\n",
1313*d83cc019SAndroid Build Coastguard Worker strerror(errno));
1314*d83cc019SAndroid Build Coastguard Worker close(testdirfd);
1315*d83cc019SAndroid Build Coastguard Worker close(resdirfd);
1316*d83cc019SAndroid Build Coastguard Worker return false;
1317*d83cc019SAndroid Build Coastguard Worker }
1318*d83cc019SAndroid Build Coastguard Worker
1319*d83cc019SAndroid Build Coastguard Worker if ((timefd = openat(resdirfd, "starttime.txt", O_CREAT | O_WRONLY | O_EXCL, 0666)) >= 0) {
1320*d83cc019SAndroid Build Coastguard Worker /*
1321*d83cc019SAndroid Build Coastguard Worker * Ignore failure to open. If this is a resume, we
1322*d83cc019SAndroid Build Coastguard Worker * don't want to overwrite. For other errors, we
1323*d83cc019SAndroid Build Coastguard Worker * ignore the start time.
1324*d83cc019SAndroid Build Coastguard Worker */
1325*d83cc019SAndroid Build Coastguard Worker dprintf(timefd, "%f\n", timeofday_double());
1326*d83cc019SAndroid Build Coastguard Worker close(timefd);
1327*d83cc019SAndroid Build Coastguard Worker }
1328*d83cc019SAndroid Build Coastguard Worker
1329*d83cc019SAndroid Build Coastguard Worker oom_immortal();
1330*d83cc019SAndroid Build Coastguard Worker
1331*d83cc019SAndroid Build Coastguard Worker sigemptyset(&sigmask);
1332*d83cc019SAndroid Build Coastguard Worker sigaddset(&sigmask, SIGCHLD);
1333*d83cc019SAndroid Build Coastguard Worker sigaddset(&sigmask, SIGINT);
1334*d83cc019SAndroid Build Coastguard Worker sigaddset(&sigmask, SIGTERM);
1335*d83cc019SAndroid Build Coastguard Worker sigaddset(&sigmask, SIGQUIT);
1336*d83cc019SAndroid Build Coastguard Worker sigaddset(&sigmask, SIGHUP);
1337*d83cc019SAndroid Build Coastguard Worker sigfd = signalfd(-1, &sigmask, O_CLOEXEC);
1338*d83cc019SAndroid Build Coastguard Worker sigprocmask(SIG_BLOCK, &sigmask, NULL);
1339*d83cc019SAndroid Build Coastguard Worker
1340*d83cc019SAndroid Build Coastguard Worker if (sigfd < 0) {
1341*d83cc019SAndroid Build Coastguard Worker /* TODO: Handle better */
1342*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Cannot mask signals\n");
1343*d83cc019SAndroid Build Coastguard Worker status = false;
1344*d83cc019SAndroid Build Coastguard Worker goto end;
1345*d83cc019SAndroid Build Coastguard Worker }
1346*d83cc019SAndroid Build Coastguard Worker
1347*d83cc019SAndroid Build Coastguard Worker init_watchdogs(settings);
1348*d83cc019SAndroid Build Coastguard Worker
1349*d83cc019SAndroid Build Coastguard Worker if (!uname(&unamebuf)) {
1350*d83cc019SAndroid Build Coastguard Worker dprintf(unamefd, "%s %s %s %s %s\n",
1351*d83cc019SAndroid Build Coastguard Worker unamebuf.sysname,
1352*d83cc019SAndroid Build Coastguard Worker unamebuf.nodename,
1353*d83cc019SAndroid Build Coastguard Worker unamebuf.release,
1354*d83cc019SAndroid Build Coastguard Worker unamebuf.version,
1355*d83cc019SAndroid Build Coastguard Worker unamebuf.machine);
1356*d83cc019SAndroid Build Coastguard Worker } else {
1357*d83cc019SAndroid Build Coastguard Worker dprintf(unamefd, "uname() failed\n");
1358*d83cc019SAndroid Build Coastguard Worker }
1359*d83cc019SAndroid Build Coastguard Worker close(unamefd);
1360*d83cc019SAndroid Build Coastguard Worker
1361*d83cc019SAndroid Build Coastguard Worker /* Check if we're already in abort-state at bootup */
1362*d83cc019SAndroid Build Coastguard Worker if (!state->resuming) {
1363*d83cc019SAndroid Build Coastguard Worker char *reason;
1364*d83cc019SAndroid Build Coastguard Worker
1365*d83cc019SAndroid Build Coastguard Worker if ((reason = need_to_abort(settings)) != NULL) {
1366*d83cc019SAndroid Build Coastguard Worker char *nexttest = entry_display_name(&job_list->entries[state->next]);
1367*d83cc019SAndroid Build Coastguard Worker write_abort_file(resdirfd, reason, "nothing", nexttest);
1368*d83cc019SAndroid Build Coastguard Worker free(reason);
1369*d83cc019SAndroid Build Coastguard Worker free(nexttest);
1370*d83cc019SAndroid Build Coastguard Worker
1371*d83cc019SAndroid Build Coastguard Worker status = false;
1372*d83cc019SAndroid Build Coastguard Worker
1373*d83cc019SAndroid Build Coastguard Worker goto end;
1374*d83cc019SAndroid Build Coastguard Worker }
1375*d83cc019SAndroid Build Coastguard Worker }
1376*d83cc019SAndroid Build Coastguard Worker
1377*d83cc019SAndroid Build Coastguard Worker for (; state->next < job_list->size;
1378*d83cc019SAndroid Build Coastguard Worker state->next++) {
1379*d83cc019SAndroid Build Coastguard Worker char *reason;
1380*d83cc019SAndroid Build Coastguard Worker int result;
1381*d83cc019SAndroid Build Coastguard Worker
1382*d83cc019SAndroid Build Coastguard Worker if (should_die_because_signal(sigfd)) {
1383*d83cc019SAndroid Build Coastguard Worker status = false;
1384*d83cc019SAndroid Build Coastguard Worker goto end;
1385*d83cc019SAndroid Build Coastguard Worker }
1386*d83cc019SAndroid Build Coastguard Worker
1387*d83cc019SAndroid Build Coastguard Worker result = execute_next_entry(state,
1388*d83cc019SAndroid Build Coastguard Worker job_list->size,
1389*d83cc019SAndroid Build Coastguard Worker &time_spent,
1390*d83cc019SAndroid Build Coastguard Worker settings,
1391*d83cc019SAndroid Build Coastguard Worker &job_list->entries[state->next],
1392*d83cc019SAndroid Build Coastguard Worker testdirfd, resdirfd,
1393*d83cc019SAndroid Build Coastguard Worker sigfd, &sigmask);
1394*d83cc019SAndroid Build Coastguard Worker
1395*d83cc019SAndroid Build Coastguard Worker if (result < 0) {
1396*d83cc019SAndroid Build Coastguard Worker status = false;
1397*d83cc019SAndroid Build Coastguard Worker break;
1398*d83cc019SAndroid Build Coastguard Worker }
1399*d83cc019SAndroid Build Coastguard Worker
1400*d83cc019SAndroid Build Coastguard Worker reduce_time_left(settings, state, time_spent);
1401*d83cc019SAndroid Build Coastguard Worker
1402*d83cc019SAndroid Build Coastguard Worker if (overall_timeout_exceeded(state)) {
1403*d83cc019SAndroid Build Coastguard Worker if (settings->log_level >= LOG_LEVEL_NORMAL) {
1404*d83cc019SAndroid Build Coastguard Worker printf("Overall timeout time exceeded, stopping.\n");
1405*d83cc019SAndroid Build Coastguard Worker }
1406*d83cc019SAndroid Build Coastguard Worker
1407*d83cc019SAndroid Build Coastguard Worker break;
1408*d83cc019SAndroid Build Coastguard Worker }
1409*d83cc019SAndroid Build Coastguard Worker
1410*d83cc019SAndroid Build Coastguard Worker if ((reason = need_to_abort(settings)) != NULL) {
1411*d83cc019SAndroid Build Coastguard Worker char *prev = entry_display_name(&job_list->entries[state->next]);
1412*d83cc019SAndroid Build Coastguard Worker char *next = (state->next + 1 < job_list->size ?
1413*d83cc019SAndroid Build Coastguard Worker entry_display_name(&job_list->entries[state->next + 1]) :
1414*d83cc019SAndroid Build Coastguard Worker strdup("nothing"));
1415*d83cc019SAndroid Build Coastguard Worker write_abort_file(resdirfd, reason, prev, next);
1416*d83cc019SAndroid Build Coastguard Worker free(prev);
1417*d83cc019SAndroid Build Coastguard Worker free(next);
1418*d83cc019SAndroid Build Coastguard Worker free(reason);
1419*d83cc019SAndroid Build Coastguard Worker status = false;
1420*d83cc019SAndroid Build Coastguard Worker break;
1421*d83cc019SAndroid Build Coastguard Worker }
1422*d83cc019SAndroid Build Coastguard Worker
1423*d83cc019SAndroid Build Coastguard Worker if (result > 0) {
1424*d83cc019SAndroid Build Coastguard Worker double time_left = state->time_left;
1425*d83cc019SAndroid Build Coastguard Worker
1426*d83cc019SAndroid Build Coastguard Worker close_watchdogs(settings);
1427*d83cc019SAndroid Build Coastguard Worker sigprocmask(SIG_UNBLOCK, &sigmask, NULL);
1428*d83cc019SAndroid Build Coastguard Worker /* make sure that we do not leave any signals unhandled */
1429*d83cc019SAndroid Build Coastguard Worker if (should_die_because_signal(sigfd)) {
1430*d83cc019SAndroid Build Coastguard Worker status = false;
1431*d83cc019SAndroid Build Coastguard Worker goto end_post_signal_restore;
1432*d83cc019SAndroid Build Coastguard Worker }
1433*d83cc019SAndroid Build Coastguard Worker close(sigfd);
1434*d83cc019SAndroid Build Coastguard Worker close(testdirfd);
1435*d83cc019SAndroid Build Coastguard Worker initialize_execute_state_from_resume(resdirfd, state, settings, job_list);
1436*d83cc019SAndroid Build Coastguard Worker state->time_left = time_left;
1437*d83cc019SAndroid Build Coastguard Worker return execute(state, settings, job_list);
1438*d83cc019SAndroid Build Coastguard Worker }
1439*d83cc019SAndroid Build Coastguard Worker }
1440*d83cc019SAndroid Build Coastguard Worker
1441*d83cc019SAndroid Build Coastguard Worker if ((timefd = openat(resdirfd, "endtime.txt", O_CREAT | O_WRONLY | O_EXCL, 0666)) >= 0) {
1442*d83cc019SAndroid Build Coastguard Worker dprintf(timefd, "%f\n", timeofday_double());
1443*d83cc019SAndroid Build Coastguard Worker close(timefd);
1444*d83cc019SAndroid Build Coastguard Worker }
1445*d83cc019SAndroid Build Coastguard Worker
1446*d83cc019SAndroid Build Coastguard Worker end:
1447*d83cc019SAndroid Build Coastguard Worker close_watchdogs(settings);
1448*d83cc019SAndroid Build Coastguard Worker sigprocmask(SIG_UNBLOCK, &sigmask, NULL);
1449*d83cc019SAndroid Build Coastguard Worker /* make sure that we do not leave any signals unhandled */
1450*d83cc019SAndroid Build Coastguard Worker if (should_die_because_signal(sigfd))
1451*d83cc019SAndroid Build Coastguard Worker status = false;
1452*d83cc019SAndroid Build Coastguard Worker end_post_signal_restore:
1453*d83cc019SAndroid Build Coastguard Worker close(sigfd);
1454*d83cc019SAndroid Build Coastguard Worker close(testdirfd);
1455*d83cc019SAndroid Build Coastguard Worker close(resdirfd);
1456*d83cc019SAndroid Build Coastguard Worker return status;
1457*d83cc019SAndroid Build Coastguard Worker }
1458