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