/*
 * dev/kill-eintr.c: seccomp(2) race reproducer
 * Copyright (c) 2025 Ali Polatel <alip@chesswob.org>
 * Based in part upon python's test_signal.py
 * Released under the same license as Python.
 */

#define _POSIX_C_SOURCE 200809L
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <time.h>

void handler(int signum) {}

void setsig(int signum)
{
	struct sigaction sa;
	memset(&sa, 0, sizeof(sa));
	sa.sa_handler = handler;
	sa.sa_flags = 0;
	sigemptyset(&sa.sa_mask);
	if (sigaction(signum, &sa, NULL) == -1) {
		perror("sigaction");
		exit(EXIT_FAILURE);
	}
}

int main(void)
{
	const int N = 10000;
	int i, save_errno;
	pid_t pid = getpid();

	setsig(SIGUSR2);
	setsig(SIGALRM); // for ITIMER_REAL

	struct itimerval it, old_it;
	memset(&it, 0, sizeof(it));
	it.it_value.tv_sec = 0;
	it.it_value.tv_usec = 1; // 1us

	printf("Starting stress test with %d iterations...\n", N);
	for (i = 0; i < N; i++) {
		it.it_value.tv_usec = 1 + (rand() % 10);

		if (setitimer(ITIMER_REAL, &it, &old_it) == -1) {
			save_errno = errno;
			perror("setitimer");
			exit(save_errno);
		}

		if (kill(pid, SIGUSR2) == -1) {
			int save_errno = errno;
			printf("kill failed at iteration %d: %d (%s)\n",
			       i, errno, strerror(errno));
			exit(save_errno);
		}
	}

	printf("Completed %d iterations without EINTR.\n", N);
	return 0;
}
