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