1/*
2 * Copyright 2007, Axel Dörfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include <errno.h>
8#include <signal.h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
12#include <unistd.h>
13
14
15#if defined(__BEOS__) && !defined(__HAIKU__)
16typedef void (*sighandler_t)(int);
17#	define SIGSTKSZ		16384
18#	define SA_ONESHOT	0
19#	define SA_ONSTACK	0
20#	define SA_RESTART	0
21#	define ualarm(usec, interval) alarm(1)
22#endif
23
24#if !defined(__USE_GNU)
25// sighandler is a GNU extension. This matches the check
26// in signal.h.  We may want to use posix sigaction though
27// in the future which is posix
28typedef void (*sighandler_t)(int);
29#endif
30
31
32const void* kUserDataMagic = (void *)0x12345678;
33
34static char sAlternateStack[SIGSTKSZ];
35
36
37bool
38is_alternate(void* pointer)
39{
40	return (char*)pointer > &sAlternateStack[0]
41		&& (char*)pointer <= &sAlternateStack[0] + SIGSTKSZ;
42}
43
44
45void
46sigHandler(int signal, void *userData, vregs *regs)
47{
48#if defined(__BEOS__) || defined(__HAIKU__)
49	if (userData != kUserDataMagic)
50		fprintf(stderr, "FAILED: user data not correct: %p\n", userData);
51#endif
52
53	printf("signal handler called with signal %i on %s stack\n",
54		signal, is_alternate(&signal) ? "alternate" : "standard");
55}
56
57
58void
59wait_for_key()
60{
61	char buffer[100];
62	if (fgets(buffer, sizeof(buffer), stdin) == NULL
63		|| buffer[0] == 'q') {
64		if (errno == EINTR)
65			puts("interrupted");
66		else
67			exit(0);
68	}
69}
70
71int
72main()
73{
74	puts("-- 1 (should block) --");
75
76	struct sigaction newAction;
77	newAction.sa_handler = (sighandler_t)sigHandler;
78	newAction.sa_mask = 0;
79	newAction.sa_flags = SA_ONESHOT | SA_ONSTACK | SA_RESTART;
80#if defined(__BEOS__) || defined(__HAIKU__)
81	newAction.sa_userdata = (void*)kUserDataMagic;
82#endif
83	sigaction(SIGALRM, &newAction, NULL);
84
85	ualarm(10000, 0);
86	wait_for_key();
87
88	puts("-- 2 (does not block, should call handler twice) --");
89
90	newAction.sa_flags = 0;
91	sigaction(SIGALRM, &newAction, NULL);
92
93	ualarm(0, 50000);
94	wait_for_key();
95	wait_for_key();
96
97	ualarm(0, 0);
98
99	puts("-- 3 (alternate stack, should block) --");
100
101#if defined(__BEOS__) && !defined(__HAIKU__)
102	set_signal_stack(sAlternateStack, SIGSTKSZ);
103#else
104	stack_t newStack;
105	newStack.ss_sp = sAlternateStack;
106	newStack.ss_size = SIGSTKSZ;
107	newStack.ss_flags = 0;
108	if (sigaltstack(&newStack, NULL) != 0)
109		fprintf(stderr, "sigaltstack() failed: %s\n", strerror(errno));
110#endif
111
112	newAction.sa_flags = SA_RESTART | SA_ONSTACK;
113	sigaction(SIGALRM, &newAction, NULL);
114
115	ualarm(10000, 0);
116	wait_for_key();
117
118	puts("-- end --");
119	return 0;
120}
121