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 stress test aims to test the following assertions: 18 * -> pthread_kill() does not make the system unstable 19 * -> no signal get lost when they are not already pending. 20 21 * The steps are: 22 * -> create 2 threads which send signals heavily to a 3rd thread. 23 * -> Create another thread which sends a signal synchronously to another one. 24 25 * The test fails if a signal is lost. The other assertion is tested implicitely 26 27 */ 28 29 /* We are testing conformance to IEEE Std 1003.1, 2003 Edition */ 30 #define _POSIX_C_SOURCE 200112L 31 32 /********************************************************************************************/ 33 /****************************** standard includes *****************************************/ 34 /********************************************************************************************/ 35 #include <pthread.h> 36 #include <stdarg.h> 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <string.h> 40 #include <unistd.h> 41 42 #include <semaphore.h> 43 #include <errno.h> 44 #include <signal.h> 45 46 /********************************************************************************************/ 47 /****************************** Test framework *****************************************/ 48 /********************************************************************************************/ 49 #include "testfrmw.h" 50 #include "testfrmw.c" 51 /* This header is responsible for defining the following macros: 52 * UNRESOLVED(ret, descr); 53 * where descr is a description of the error and ret is an int (error code for example) 54 * FAILED(descr); 55 * where descr is a short text saying why the test has failed. 56 * PASSED(); 57 * No parameter. 58 * 59 * Both three macros shall terminate the calling process. 60 * The testcase shall not terminate in any other maneer. 61 * 62 * The other file defines the functions 63 * void output_init() 64 * void output(char * string, ...) 65 * 66 * Those may be used to output information. 67 */ 68 69 /********************************************************************************************/ 70 /********************************** Configuration ******************************************/ 71 /********************************************************************************************/ 72 #ifndef VERBOSE 73 #define VERBOSE 1 74 #endif 75 76 /********************************************************************************************/ 77 /*********************************** Test cases *****************************************/ 78 /********************************************************************************************/ 79 80 char do_it = 1; 81 long long iterations = 0; 82 83 /* Handler for user request to terminate */ 84 void sighdl(int sig) 85 { 86 /* do_it = 0 */ 87 88 do { 89 do_it = 0; 90 } 91 while (do_it); 92 } 93 94 void floodsighdl(int sig) 95 { 96 /* Nothing to do */ 97 return; 98 } 99 100 /* Signals flood receiver thread */ 101 void *flood_receiver(void *arg) 102 { 103 int ret = 0; 104 /* register the signal handler for this one thread */ 105 106 struct sigaction sa; 107 sigemptyset(&sa.sa_mask); 108 sa.sa_flags = 0; 109 sa.sa_handler = floodsighdl; 110 111 if ((ret = sigaction(SIGABRT, &sa, NULL))) { 112 UNRESOLVED(ret, "Unable to register signal handler"); 113 } 114 115 if ((ret = sigaction(SIGBUS, &sa, NULL))) { 116 UNRESOLVED(ret, "Unable to register signal handler"); 117 } 118 119 /* Wait for the other threads to terminate */ 120 121 do { 122 sched_yield(); 123 } while (*(int *)arg); 124 125 return NULL; 126 } 127 128 /* Signal flood threads */ 129 void *flooder_1(void *arg) 130 { 131 int ret = 0; 132 133 while (do_it) { 134 iterations++; 135 ret = pthread_kill(*(pthread_t *) arg, SIGABRT); 136 137 if (ret != 0) { 138 UNRESOLVED(ret, "Flooder 1 thread got an error"); 139 } 140 } 141 142 return NULL; 143 } 144 145 void *flooder_2(void *arg) 146 { 147 int ret = 0; 148 149 while (do_it) { 150 iterations++; 151 ret = pthread_kill(*(pthread_t *) arg, SIGBUS); 152 153 if (ret != 0) { 154 UNRESOLVED(ret, "Flooder 1 thread got an error"); 155 } 156 } 157 158 return NULL; 159 } 160 161 /* Synchronized threads */ 162 int sync; 163 void syncsighdl(int sig) 164 { 165 /* signal we have been called */ 166 sync = 1; 167 return; 168 } 169 170 void *sync_rec(void *arg) 171 { 172 int ret = 0; 173 174 struct sigaction sa; 175 sigemptyset(&sa.sa_mask); 176 sa.sa_flags = 0; 177 sa.sa_handler = syncsighdl; 178 179 if ((ret = sigaction(SIGILL, &sa, NULL))) { 180 UNRESOLVED(ret, "Unable to register signal handler"); 181 } 182 183 /* wait until termination */ 184 do { 185 sched_yield(); 186 } while (*(int *)arg); 187 188 return NULL; 189 } 190 191 void *sync_send(void *arg) 192 { 193 int ret = 0; 194 195 while (do_it) { 196 /* Disarm the flag */ 197 sync = 0; 198 /* Send the signal */ 199 ret = pthread_kill(*(pthread_t *) arg, SIGILL); 200 201 if (ret != 0) { 202 UNRESOLVED(ret, "Failed to send signal"); 203 } 204 205 /* Sleep up to 5 sec */ 206 for (ret = 0; (ret < 5) && (sync == 0); ret++) 207 sleep(1); 208 209 /* Test if signal was received */ 210 if (sync == 0) { 211 FAILED 212 ("Signal SIGILL was not delivered within 5 second -- lost?"); 213 } 214 } 215 216 return NULL; 217 218 } 219 220 /* Main function */ 221 int main(int argc, char *argv[]) 222 { 223 int ret = 0; 224 225 int flooding = 1; 226 pthread_t fl_rec; 227 pthread_t fl_snd1, fl_snd2; 228 229 int synchro = 1; 230 pthread_t sy_rec; 231 pthread_t sy_snd; 232 233 struct sigaction sa; 234 235 /* Initialize output routine */ 236 output_init(); 237 238 /* Register the signal handler for SIGUSR1 */ 239 sigemptyset(&sa.sa_mask); 240 241 sa.sa_flags = 0; 242 243 sa.sa_handler = sighdl; 244 245 if ((ret = sigaction(SIGUSR1, &sa, NULL))) { 246 UNRESOLVED(ret, "Unable to register signal handler"); 247 } 248 249 if ((ret = sigaction(SIGALRM, &sa, NULL))) { 250 UNRESOLVED(ret, "Unable to register signal handler"); 251 } 252 #if VERBOSE > 1 253 output("[parent] Signal handler registered\n"); 254 255 #endif 256 257 ret = pthread_create(&fl_rec, NULL, flood_receiver, &flooding); 258 259 if (ret != 0) { 260 UNRESOLVED(ret, "Unable to create a thread"); 261 } 262 263 ret = pthread_create(&fl_snd1, NULL, flooder_1, &fl_rec); 264 265 if (ret != 0) { 266 UNRESOLVED(ret, "Unable to create a thread"); 267 } 268 269 ret = pthread_create(&fl_snd2, NULL, flooder_2, &fl_rec); 270 271 if (ret != 0) { 272 UNRESOLVED(ret, "Unable to create a thread"); 273 } 274 275 ret = pthread_create(&sy_rec, NULL, sync_rec, &synchro); 276 277 if (ret != 0) { 278 UNRESOLVED(ret, "Unable to create a thread"); 279 } 280 281 ret = pthread_create(&sy_snd, NULL, sync_send, &sy_rec); 282 283 if (ret != 0) { 284 UNRESOLVED(ret, "Unable to create a thread"); 285 } 286 287 /* Wait the user stops the test */ 288 ret = pthread_join(fl_snd1, NULL); 289 290 if (ret != 0) { 291 UNRESOLVED(ret, "Failed to join a thread"); 292 } 293 294 ret = pthread_join(fl_snd2, NULL); 295 296 if (ret != 0) { 297 UNRESOLVED(ret, "Failed to join a thread"); 298 } 299 300 flooding = 0; 301 ret = pthread_join(fl_rec, NULL); 302 303 if (ret != 0) { 304 UNRESOLVED(ret, "Failed to join a thread"); 305 } 306 307 ret = pthread_join(sy_snd, NULL); 308 309 if (ret != 0) { 310 UNRESOLVED(ret, "Failed to join a thread"); 311 } 312 313 synchro = 0; 314 315 ret = pthread_join(sy_rec, NULL); 316 317 if (ret != 0) { 318 UNRESOLVED(ret, "Failed to join a thread"); 319 } 320 321 /* We've been asked to stop */ 322 output("pthread_kill stress test PASSED -- %llu iterations\n", 323 iterations); 324 325 PASSED; 326 } 327