cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

harness.c (2412B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      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	5
     23
     24/* Setting timeout to -1 disables the alarm */
     25static uint64_t timeout = 120;
     26
     27int run_test(int (test_function)(void), 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		else
     82			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), 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	} else
    130		test_finish(name, rc);
    131
    132	return rc;
    133}