1 /*
2 * Copyright (c) 2004, Bull S.A.. All rights reserved.
3 * Created by: Sebastien Decugis
4
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16
17 * This sample test aims to check the following assertion:
18 *
19 * The function does not return EINTR
20
21 * The steps are:
22 * -> kill a thread which calls pthread_once
23 * -> check that EINTR is never returned
24
25 */
26
27
28 /********************************************************************************************/
29 /****************************** standard includes *****************************************/
30 /********************************************************************************************/
31 #include <errno.h>
32 #include <pthread.h>
33 #include <semaphore.h>
34 #include <signal.h>
35 #include <stdarg.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <unistd.h>
40
41 /********************************************************************************************/
42 /****************************** Test framework *****************************************/
43 /********************************************************************************************/
44 #include "../testfrmw/testfrmw.h"
45 #include "../testfrmw/testfrmw.c"
46 /* This header is responsible for defining the following macros:
47 * UNRESOLVED(ret, descr);
48 * where descr is a description of the error and ret is an int (error code for example)
49 * FAILED(descr);
50 * where descr is a short text saying why the test has failed.
51 * PASSED();
52 * No parameter.
53 *
54 * Both three macros shall terminate the calling process.
55 * The testcase shall not terminate in any other maneer.
56 *
57 * The other file defines the functions
58 * void output_init()
59 * void output(char * string, ...)
60 *
61 * Those may be used to output information.
62 */
63
64 /********************************************************************************************/
65 /********************************** Configuration ******************************************/
66 /********************************************************************************************/
67 #ifndef VERBOSE
68 #define VERBOSE 1
69 #endif
70
71 #define WITH_SYNCHRO
72
73 /********************************************************************************************/
74 /*********************************** Test cases *****************************************/
75 /********************************************************************************************/
76
77 static char do_it = 1;
78 static unsigned long count_ope = 0;
79 #ifdef WITH_SYNCHRO
80 static sem_t semsig1;
81 static sem_t semsig2;
82 static unsigned long count_sig = 0;
83 #endif
84
85 static sigset_t usersigs;
86
87 typedef struct {
88 int sig;
89 #ifdef WITH_SYNCHRO
90 sem_t *sem;
91 #endif
92 } thestruct;
93
94 /* the following function keeps on sending the signal to the process */
sendsig(void * arg)95 static void *sendsig(void *arg)
96 {
97 thestruct *thearg = (thestruct *) arg;
98 int ret;
99 pid_t process;
100
101 process = getpid();
102
103 /* We block the signals SIGUSR1 and SIGUSR2 for this THREAD */
104 ret = pthread_sigmask(SIG_BLOCK, &usersigs, NULL);
105
106 if (ret != 0) {
107 UNRESOLVED(ret,
108 "Unable to block SIGUSR1 and SIGUSR2 in signal thread");
109 }
110
111 while (do_it) {
112 #ifdef WITH_SYNCHRO
113
114 if ((ret = sem_wait(thearg->sem))) {
115 UNRESOLVED(errno, "Sem_wait in sendsig");
116 }
117
118 count_sig++;
119 #endif
120
121 ret = kill(process, thearg->sig);
122
123 if (ret != 0) {
124 UNRESOLVED(errno, "Kill in sendsig");
125 }
126
127 }
128
129 return NULL;
130 }
131
132 /* Next are the signal handlers. */
133 /* This one is registered for signal SIGUSR1 */
sighdl1(int sig PTS_ATTRIBUTE_UNUSED)134 static void sighdl1(int sig PTS_ATTRIBUTE_UNUSED)
135 {
136 #ifdef WITH_SYNCHRO
137
138 if (sem_post(&semsig1)) {
139 UNRESOLVED(errno, "Sem_post in signal handler 1");
140 }
141 #endif
142 }
143
144 /* This one is registered for signal SIGUSR2 */
sighdl2(int sig PTS_ATTRIBUTE_UNUSED)145 static void sighdl2(int sig PTS_ATTRIBUTE_UNUSED)
146 {
147 #ifdef WITH_SYNCHRO
148
149 if (sem_post(&semsig2)) {
150 UNRESOLVED(errno, "Sem_post in signal handler 2");
151 }
152 #endif
153 }
154
155 static int init_ctl;
156 /* Init function */
initializer(void)157 static void initializer(void)
158 {
159 init_ctl++;
160 return;
161 }
162
163 /* Test function -- calls pthread_equal() and checks that EINTR is never returned. */
test(void * arg PTS_ATTRIBUTE_UNUSED)164 static void *test(void *arg PTS_ATTRIBUTE_UNUSED)
165 {
166 int ret = 0;
167
168 /* We don't block the signals SIGUSR1 and SIGUSR2 for this THREAD */
169 ret = pthread_sigmask(SIG_UNBLOCK, &usersigs, NULL);
170
171 if (ret != 0) {
172 UNRESOLVED(ret,
173 "Unable to unblock SIGUSR1 and SIGUSR2 in worker thread");
174 }
175
176 while (do_it) {
177
178 pthread_once_t once_ctl = PTHREAD_ONCE_INIT;
179
180 count_ope++;
181
182 init_ctl = 0;
183
184 ret = pthread_once(&once_ctl, initializer);
185
186 if (ret == EINTR) {
187 FAILED("pthread_once returned EINTR");
188 }
189
190 if (ret != 0) {
191 UNRESOLVED(ret, "pthread_once failed");
192 }
193
194 ret = pthread_once(&once_ctl, initializer);
195
196 if (ret == EINTR) {
197 FAILED("pthread_once returned EINTR");
198 }
199
200 if (ret != 0) {
201 UNRESOLVED(ret, "pthread_once failed");
202 }
203
204 if (init_ctl != 1) {
205 output("init_ctl: %d\n", init_ctl);
206 FAILED("The initializer did not execute as expected");
207 }
208
209 }
210
211 return NULL;
212 }
213
214 /* Main function */
main(void)215 int main(void)
216 {
217 int ret;
218 pthread_t th_work, th_sig1, th_sig2;
219 thestruct arg1, arg2;
220
221 struct sigaction sa;
222
223 /* Initialize output routine */
224 output_init();
225
226 /* We need to register the signal handlers for the PROCESS */
227 sigemptyset(&sa.sa_mask);
228 sa.sa_flags = 0;
229 sa.sa_handler = sighdl1;
230
231 if ((ret = sigaction(SIGUSR1, &sa, NULL)) == -1) {
232 UNRESOLVED(ret, "Unable to register signal handler1");
233 }
234
235 sa.sa_handler = sighdl2;
236
237 if ((ret = sigaction(SIGUSR2, &sa, NULL)) == -1) {
238 UNRESOLVED(ret, "Unable to register signal handler2");
239 }
240
241 /* We prepare a signal set which includes SIGUSR1 and SIGUSR2 */
242 sigemptyset(&usersigs);
243
244 ret = sigaddset(&usersigs, SIGUSR1);
245
246 ret |= sigaddset(&usersigs, SIGUSR2);
247
248 if (ret != 0) {
249 UNRESOLVED(ret, "Unable to add SIGUSR1 or 2 to a signal set");
250 }
251
252 /* We now block the signals SIGUSR1 and SIGUSR2 for this THREAD */
253 ret = pthread_sigmask(SIG_BLOCK, &usersigs, NULL);
254
255 if (ret != 0) {
256 UNRESOLVED(ret,
257 "Unable to block SIGUSR1 and SIGUSR2 in main thread");
258 }
259 #ifdef WITH_SYNCHRO
260 if (sem_init(&semsig1, 0, 1)) {
261 UNRESOLVED(errno, "Semsig1 init");
262 }
263
264 if (sem_init(&semsig2, 0, 1)) {
265 UNRESOLVED(errno, "Semsig2 init");
266 }
267 #endif
268
269 if ((ret = pthread_create(&th_work, NULL, test, NULL))) {
270 UNRESOLVED(ret, "Worker thread creation failed");
271 }
272
273 arg1.sig = SIGUSR1;
274 arg2.sig = SIGUSR2;
275 #ifdef WITH_SYNCHRO
276 arg1.sem = &semsig1;
277 arg2.sem = &semsig2;
278 #endif
279
280 if ((ret = pthread_create(&th_sig1, NULL, sendsig, (void *)&arg1))) {
281 UNRESOLVED(ret, "Signal 1 sender thread creation failed");
282 }
283
284 if ((ret = pthread_create(&th_sig2, NULL, sendsig, (void *)&arg2))) {
285 UNRESOLVED(ret, "Signal 2 sender thread creation failed");
286 }
287
288 /* Let's wait for a while now */
289 sleep(1);
290
291 /* Now stop the threads and join them */
292 do {
293 do_it = 0;
294 }
295 while (do_it);
296
297 if ((ret = pthread_join(th_sig1, NULL))) {
298 UNRESOLVED(ret, "Signal 1 sender thread join failed");
299 }
300
301 if ((ret = pthread_join(th_sig2, NULL))) {
302 UNRESOLVED(ret, "Signal 2 sender thread join failed");
303 }
304
305 if ((ret = pthread_join(th_work, NULL))) {
306 UNRESOLVED(ret, "Worker thread join failed");
307 }
308 #if VERBOSE > 0
309 output("Test executed successfully.\n");
310
311 output(" %d initializations.\n", count_ope);
312
313 #ifdef WITH_SYNCHRO
314 output(" %d signals were sent meanwhile.\n", count_sig);
315
316 #endif
317 #endif
318 PASSED;
319 }
320