Home | History | Annotate | Download | only in pthread_kill
      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