1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright 2013 David Hoeppner. All rights reserved.
14 */
15
16 /*
17 * Queue maximum number of signals and test if we can queue more signals then
18 * allowed.
19 */
20
21 #include <sys/types.h>
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <signal.h>
27
28 #define SIGQUEUE_SIGNAL SIGRTMIN /* Signal used for testing */
29
30 int nreceived = 0;
31
32 static void
test_start(const char * test_name,const char * format,...)33 test_start(const char *test_name, const char *format, ...)
34 {
35 va_list args;
36
37 (void) printf("TEST STARTING %s: ", test_name);
38
39 va_start(args, format);
40 (void) vprintf(format, args);
41 va_end(args);
42 (void) fflush(stdout);
43 }
44
45 static void
test_failed(const char * test_name,const char * format,...)46 test_failed(const char *test_name, const char *format, ...)
47 {
48 va_list args;
49
50 (void) printf("TEST FAILED %s: ", test_name);
51
52 va_start(args, format);
53 (void) vprintf(format, args);
54 va_end(args);
55
56 (void) exit(-1);
57 }
58
59 static void
test_passed(const char * test_name)60 test_passed(const char *test_name)
61 {
62 (void) printf("TEST PASS: %s\n", test_name);
63 (void) fflush(stdout);
64 }
65
66 /* ARGSUSED */
67 static void
maximum_test_handler(int signal,siginfo_t * siginfo,void * context)68 maximum_test_handler(int signal, siginfo_t *siginfo, void *context)
69 {
70 nreceived++;
71 }
72
73 static void
sigqueue_maximum_test(void)74 sigqueue_maximum_test(void)
75 {
76 const char *test_name = __func__;
77 struct sigaction action;
78 long sigqueue_max, i;
79 pid_t pid;
80 union sigval value;
81 int error;
82
83 test_start(test_name, "queue maximum number of signals\n");
84
85 /*
86 * Get the maximum size of the queue.
87 */
88 sigqueue_max = sysconf(_SC_SIGQUEUE_MAX);
89 if (sigqueue_max == -1) {
90 test_failed(test_name, "sysconf\n");
91 }
92
93 /*
94 * Put the signal on hold.
95 */
96 error = sighold(SIGQUEUE_SIGNAL);
97 if (error == -1) {
98 test_failed(test_name, "sighold\n");
99 }
100
101 pid = getpid();
102 value.sival_int = 0;
103
104 action.sa_flags = SA_SIGINFO;
105 action.sa_sigaction = maximum_test_handler;
106
107 error = sigemptyset(&action.sa_mask);
108 if (error == -1) {
109 test_failed(test_name, "sigemptyset\n");
110 }
111
112 /*
113 * Set signal handler.
114 */
115 error = sigaction(SIGQUEUE_SIGNAL, &action, 0);
116 if (error == -1) {
117 test_failed(test_name, "sigaction\n");
118 }
119
120 /*
121 * Fill the signal queue to the maximum.
122 */
123 for (i = 0; i < sigqueue_max; i++) {
124 error = sigqueue(pid, SIGQUEUE_SIGNAL, value);
125 if (error == -1) {
126 test_failed(test_name, "sigqueue\n");
127 }
128 }
129
130 /*
131 * Send a further signal and test if we get the expected
132 * error.
133 */
134 error = sigqueue(pid, SIGQUEUE_SIGNAL, value);
135 if (error != -1) {
136 test_failed(test_name, "sigqueue\n");
137 }
138
139 /*
140 * Unblock the signals and check if we received all messages
141 * from the signal queue.
142 */
143 error = sigrelse(SIGQUEUE_SIGNAL);
144 if (error == -1) {
145 test_failed(test_name, "sigrelse\n");
146 }
147
148 if (nreceived != sigqueue_max) {
149 test_failed(test_name, "nreceived != sigqueue_max\n");
150 }
151
152 test_passed(test_name);
153 }
154
155 static void
run_tests(void)156 run_tests(void)
157 {
158 sigqueue_maximum_test();
159 }
160
161 /* ARGSUSED */
162 int
main(int argc,char * argv[])163 main(int argc, char *argv[])
164 {
165 run_tests();
166
167 return (EXIT_SUCCESS);
168 }
169