Home | History | Annotate | Download | only in pthread_cancel
      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 assertion:
     18 
     19 *  Heavy cancelation does not break the system or the user application.
     20 
     21 * The steps are:
     22 * Create some threads which:
     23 *  Create a thread.
     24 *  Cancel this thread, as it terminates.
     25 *  Check the return value.
     26 
     27 */
     28 
     29 /********************************************************************************************/
     30 /****************************** standard includes *****************************************/
     31 /********************************************************************************************/
     32 #include <pthread.h>
     33 #include <stdarg.h>
     34 #include <stdio.h>
     35 #include <stdlib.h>
     36 #include <string.h>
     37 #include <unistd.h>
     38 
     39 #include <errno.h>
     40 #include <signal.h>
     41 
     42 /********************************************************************************************/
     43 /******************************   Test framework   *****************************************/
     44 /********************************************************************************************/
     45 #include "testfrmw.h"
     46 #include "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 NTHREADS 30
     73 
     74 /********************************************************************************************/
     75 /***********************************    Test cases  *****************************************/
     76 /********************************************************************************************/
     77 
     78 char do_it = 1;
     79 
     80 /* Handler for user request to terminate */
     81 void sighdl(int sig)
     82 {
     83 	do {
     84 		do_it = 0;
     85 	}
     86 	while (do_it);
     87 }
     88 
     89 long long canceled, ended;
     90 
     91 /* The canceled thread */
     92 void *th(void *arg)
     93 {
     94 	int ret = 0;
     95 	ret = pthread_barrier_wait(arg);
     96 
     97 	if ((ret != 0) && (ret != PTHREAD_BARRIER_SERIAL_THREAD)) {
     98 		UNRESOLVED(ret, "Failed to wait for the barrier");
     99 	}
    100 
    101 	return NULL;
    102 }
    103 
    104 /* Thread function */
    105 void *threaded(void *arg)
    106 {
    107 	int ret = 0;
    108 	pthread_t child;
    109 
    110 	/* Initialize the barrier */
    111 	ret = pthread_barrier_init(arg, NULL, 2);
    112 
    113 	if (ret != 0) {
    114 		UNRESOLVED(ret, "Failed to initialize a barrier");
    115 	}
    116 
    117 	while (do_it) {
    118 		/* Create the thread */
    119 		ret = pthread_create(&child, NULL, th, arg);
    120 
    121 		if (ret != 0) {
    122 			UNRESOLVED(ret, "Thread creation failed");
    123 		}
    124 
    125 		/* Synchronize */
    126 		ret = pthread_barrier_wait(arg);
    127 
    128 		if ((ret != 0) && (ret != PTHREAD_BARRIER_SERIAL_THREAD)) {
    129 			UNRESOLVED(ret, "Failed to wait for the barrier");
    130 		}
    131 
    132 		/* Cancel the thread */
    133 		ret = pthread_cancel(child);
    134 
    135 		if (ret == 0)
    136 			canceled++;
    137 		else
    138 			ended++;
    139 
    140 		/* Join the thread */
    141 		ret = pthread_join(child, NULL);
    142 
    143 		if (ret != 0) {
    144 			UNRESOLVED(ret, "Unable to join the child");
    145 		}
    146 
    147 	}
    148 
    149 	/* Destroy the barrier */
    150 	ret = pthread_barrier_destroy(arg);
    151 
    152 	if (ret != 0) {
    153 		UNRESOLVED(ret, "Failed to destroy a barrier");
    154 	}
    155 
    156 	return NULL;
    157 }
    158 
    159 /* Main function */
    160 int main(int argc, char *argv[])
    161 {
    162 	int ret = 0, i;
    163 
    164 	struct sigaction sa;
    165 
    166 	pthread_t th[NTHREADS];
    167 	pthread_barrier_t b[NTHREADS];
    168 
    169 	/* Initialize output routine */
    170 	output_init();
    171 
    172 	/* Register the signal handler for SIGUSR1 */
    173 	sigemptyset(&sa.sa_mask);
    174 
    175 	sa.sa_flags = 0;
    176 
    177 	sa.sa_handler = sighdl;
    178 
    179 	if ((ret = sigaction(SIGUSR1, &sa, NULL))) {
    180 		UNRESOLVED(ret, "Unable to register signal handler");
    181 	}
    182 
    183 	if ((ret = sigaction(SIGALRM, &sa, NULL))) {
    184 		UNRESOLVED(ret, "Unable to register signal handler");
    185 	}
    186 #if VERBOSE > 1
    187 	output("[parent] Signal handler registered\n");
    188 
    189 #endif
    190 
    191 	for (i = 0; i < NTHREADS; i++) {
    192 		ret = pthread_create(&th[i], NULL, threaded, &b[i]);
    193 
    194 		if (ret != 0) {
    195 			UNRESOLVED(ret, "Failed to create a thread");
    196 		}
    197 	}
    198 
    199 #if VERBOSE > 1
    200 	output("[parent] All threads are running\n");
    201 
    202 #endif
    203 
    204 	/* Then join */
    205 	for (i = 0; i < NTHREADS; i++) {
    206 		ret = pthread_join(th[i], NULL);
    207 
    208 		if (ret != 0) {
    209 			UNRESOLVED(ret, "Failed to join a thread");
    210 		}
    211 	}
    212 
    213 	/* We've been asked to stop */
    214 
    215 	output("pthread_cancel stress test PASSED\n");
    216 
    217 	output(" - %llu threads canceled\n", canceled);
    218 
    219 	output(" - %llu threads ended\n", ended);
    220 
    221 	PASSED;
    222 }
    223