⛏️ index : haiku.git

/*
 * Copyright 2007, Axel DΓΆrfler, axeld@pinc-software.de.
 * Distributed under the terms of the MIT License.
 */


#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>


#if defined(__BEOS__) && !defined(__HAIKU__)
typedef void (*sighandler_t)(int);
#	define SIGSTKSZ		16384
#	define SA_ONESHOT	0
#	define SA_ONSTACK	0
#	define SA_RESTART	0
#	define ualarm(usec, interval) alarm(1)
#endif

#if !defined(__USE_GNU)
// sighandler is a GNU extension. This matches the check
// in signal.h.  We may want to use posix sigaction though
// in the future which is posix
typedef void (*sighandler_t)(int);
#endif


const void* kUserDataMagic = (void *)0x12345678;

static char sAlternateStack[SIGSTKSZ];


bool
is_alternate(void* pointer)
{
	return (char*)pointer > &sAlternateStack[0]
		&& (char*)pointer <= &sAlternateStack[0] + SIGSTKSZ;
}


void
sigHandler(int signal, void *userData, vregs *regs)
{
#if defined(__BEOS__) || defined(__HAIKU__)
	if (userData != kUserDataMagic)
		fprintf(stderr, "FAILED: user data not correct: %p\n", userData);
#endif

	printf("signal handler called with signal %i on %s stack\n",
		signal, is_alternate(&signal) ? "alternate" : "standard");
}


void
wait_for_key()
{
	char buffer[100];
	if (fgets(buffer, sizeof(buffer), stdin) == NULL
		|| buffer[0] == 'q') {
		if (errno == EINTR)
			puts("interrupted");
		else
			exit(0);
	}
}

int
main()
{
	puts("-- 1 (should block) --");

	struct sigaction newAction;
	newAction.sa_handler = (sighandler_t)sigHandler;
	newAction.sa_mask = 0;
	newAction.sa_flags = SA_ONESHOT | SA_ONSTACK | SA_RESTART;
#if defined(__BEOS__) || defined(__HAIKU__)
	newAction.sa_userdata = (void*)kUserDataMagic;
#endif
	sigaction(SIGALRM, &newAction, NULL);

	ualarm(10000, 0);
	wait_for_key();

	puts("-- 2 (does not block, should call handler twice) --");

	newAction.sa_flags = 0;
	sigaction(SIGALRM, &newAction, NULL);

	ualarm(0, 50000);
	wait_for_key();
	wait_for_key();

	ualarm(0, 0);

	puts("-- 3 (alternate stack, should block) --");

#if defined(__BEOS__) && !defined(__HAIKU__)
	set_signal_stack(sAlternateStack, SIGSTKSZ);
#else
	stack_t newStack;
	newStack.ss_sp = sAlternateStack;
	newStack.ss_size = SIGSTKSZ;
	newStack.ss_flags = 0;
	if (sigaltstack(&newStack, NULL) != 0)
		fprintf(stderr, "sigaltstack() failed: %s\n", strerror(errno));
#endif

	newAction.sa_flags = SA_RESTART | SA_ONSTACK;
	sigaction(SIGALRM, &newAction, NULL);

	ualarm(10000, 0);
	wait_for_key();

	puts("-- end --");
	return 0;
}