brintos

brintos / linux-shallow public Read only

0
0
Text · 2.4 KiB · 5876220 Raw
134 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright 2013, Michael Ellerman, IBM Corp.4 */5 6#include <errno.h>7#include <signal.h>8#include <stdbool.h>9#include <stdio.h>10#include <stdlib.h>11#include <sys/types.h>12#include <sys/wait.h>13#include <unistd.h>14#include <elf.h>15#include <fcntl.h>16#include <link.h>17#include <sys/stat.h>18 19#include "subunit.h"20#include "utils.h"21 22#define KILL_TIMEOUT	523 24/* Setting timeout to -1 disables the alarm */25static uint64_t timeout = 120;26 27int run_test(int (test_function)(void), const char *name)28{29	bool terminated;30	int rc, status;31	pid_t pid;32 33	/* Make sure output is flushed before forking */34	fflush(stdout);35 36	pid = fork();37	if (pid == 0) {38		setpgid(0, 0);39		exit(test_function());40	} else if (pid == -1) {41		perror("fork");42		return 1;43	}44 45	setpgid(pid, pid);46 47	if (timeout != -1)48		/* Wake us up in timeout seconds */49		alarm(timeout);50	terminated = false;51 52wait:53	rc = waitpid(pid, &status, 0);54	if (rc == -1) {55		if (errno != EINTR) {56			printf("unknown error from waitpid\n");57			return 1;58		}59 60		if (terminated) {61			printf("!! force killing %s\n", name);62			kill(-pid, SIGKILL);63			return 1;64		} else {65			printf("!! killing %s\n", name);66			kill(-pid, SIGTERM);67			terminated = true;68			alarm(KILL_TIMEOUT);69			goto wait;70		}71	}72 73	/* Kill anything else in the process group that is still running */74	kill(-pid, SIGTERM);75 76	if (WIFEXITED(status))77		status = WEXITSTATUS(status);78	else {79		if (WIFSIGNALED(status))80			printf("!! child died by signal %d\n", WTERMSIG(status));81		else82			printf("!! child died by unknown cause\n");83 84		status = 1; /* Signal or other */85	}86 87	return status;88}89 90static void sig_handler(int signum)91{92	/* Just wake us up from waitpid */93}94 95static struct sigaction sig_action = {96	.sa_handler = sig_handler,97};98 99void test_harness_set_timeout(uint64_t time)100{101	timeout = time;102}103 104int test_harness(int (test_function)(void), const char *name)105{106	int rc;107 108	test_start(name);109	test_set_git_version(GIT_VERSION);110 111	if (sigaction(SIGINT, &sig_action, NULL)) {112		perror("sigaction (sigint)");113		test_error(name);114		return 1;115	}116 117	if (sigaction(SIGALRM, &sig_action, NULL)) {118		perror("sigaction (sigalrm)");119		test_error(name);120		return 1;121	}122 123	rc = run_test(test_function, name);124 125	if (rc == MAGIC_SKIP_RETURN_VALUE) {126		test_skip(name);127		/* so that skipped test is not marked as failed */128		rc = 0;129	} else130		test_finish(name, rc);131 132	return rc;133}134