xref: /haiku/src/tests/system/libroot/posix/signal_test.cpp (revision 21258e2674226d6aa732321b6f8494841895af5f)
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
38 is_alternate(void* pointer)
39 {
40 	return (char*)pointer > &sAlternateStack[0]
41 		&& (char*)pointer <= &sAlternateStack[0] + SIGSTKSZ;
42 }
43 
44 
45 void
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
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
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