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