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__)
16 typedef 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
28 typedef void (*sighandler_t)(int);
29 #endif
30
31
32 const void* kUserDataMagic = (void *)0x12345678;
33
34 static char sAlternateStack[SIGSTKSZ];
35
36
37 bool
is_alternate(void * pointer)38 is_alternate(void* pointer)
39 {
40 return (char*)pointer > &sAlternateStack[0]
41 && (char*)pointer <= &sAlternateStack[0] + SIGSTKSZ;
42 }
43
44
45 void
sigHandler(int signal,void * userData,vregs * regs)46 sigHandler(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
58 void
wait_for_key()59 wait_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
71 int
main()72 main()
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