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
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
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
60 test_passed(const char *test_name)
61 {
62 (void) printf("TEST PASS: %s\n", test_name);
63 (void) fflush(stdout);
64 }
65
66 static void
67 maximum_test_handler(int signal, siginfo_t *siginfo, void *context)
68 {
69 nreceived++;
70 }
71
72 static void
73 sigqueue_maximum_test(void)
74 {
75 const char *test_name = __func__;
76 struct sigaction action;
77 long sigqueue_max, i;
78 pid_t pid;
79 union sigval value;
80 int error;
81
82 test_start(test_name, "queue maximum number of signals\n");
83
84 /*
85 * Get the maximum size of the queue.
86 */
87 sigqueue_max = sysconf(_SC_SIGQUEUE_MAX);
88 if (sigqueue_max == -1) {
89 test_failed(test_name, "sysconf\n");
90 }
91
92 /*
93 * Put the signal on hold.
94 */
95 error = sighold(SIGQUEUE_SIGNAL);
96 if (error == -1) {
97 test_failed(test_name, "sighold\n");
98 }
99
100 pid = getpid();
101 value.sival_int = 0;
102
103 action.sa_flags = SA_SIGINFO;
104 action.sa_sigaction = maximum_test_handler;
105
106 error = sigemptyset(&action.sa_mask);
107 if (error == -1) {
108 test_failed(test_name, "sigemptyset\n");
109 }
110
111 /*
112 * Set signal handler.
113 */
114 error = sigaction(SIGQUEUE_SIGNAL, &action, 0);
115 if (error == -1) {
116 test_failed(test_name, "sigaction\n");
117 }
118
119 /*
120 * Fill the signal queue to the maximum.
121 */
122 for (i = 0; i < sigqueue_max; i++) {
123 error = sigqueue(pid, SIGQUEUE_SIGNAL, value);
124 if (error == -1) {
125 test_failed(test_name, "sigqueue\n");
126 }
127 }
128
129 /*
130 * Send a further signal and test if we get the expected
131 * error.
132 */
133 error = sigqueue(pid, SIGQUEUE_SIGNAL, value);
134 if (error != -1) {
135 test_failed(test_name, "sigqueue\n");
136 }
137
138 /*
139 * Unblock the signals and check if we received all messages
140 * from the signal queue.
141 */
142 sigrelse(SIGQUEUE_SIGNAL);
143
144 if (nreceived != sigqueue_max) {
145 test_failed(test_name, "nreveived != sigqueue_max\n");
146 }
147
148 test_passed(test_name);
149 }
150
151 static void
152 run_tests(void)
153 {
154 sigqueue_maximum_test();
155 }
156
157 int
158 main(int argc, char *argv[])
159 {
160 run_tests();
161
162 exit(EXIT_SUCCESS);
163 }