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 /* 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 <errno.h>
     43 #include <signal.h>
     44 
     45 /********************************************************************************************/
     46 /******************************   Test framework   *****************************************/
     47 /********************************************************************************************/
     48 #include "testfrmw.h"
     49 #include "testfrmw.c"
     50 /* This header is responsible for defining the following macros:
     51  * UNRESOLVED(ret, descr);
     52  *    where descr is a description of the error and ret is an int (error code for example)
     53  * FAILED(descr);
     54  *    where descr is a short text saying why the test has failed.
     55  * PASSED();
     56  *    No parameter.
     57  *
     58  * Both three macros shall terminate the calling process.
     59  * The testcase shall not terminate in any other maneer.
     60  *
     61  * The other file defines the functions
     62  * void output_init()
     63  * void output(char * string, ...)
     64  *
     65  * Those may be used to output information.
     66  */
     67 
     68 /********************************************************************************************/
     69 /********************************** Configuration ******************************************/
     70 /********************************************************************************************/
     71 #ifndef VERBOSE
     72 #define VERBOSE 1
     73 #endif
     74 
     75 #define NTHREADS 30
     76 
     77 /********************************************************************************************/
     78 /***********************************    Test cases  *****************************************/
     79 /********************************************************************************************/
     80 
     81 char do_it = 1;
     82 
     83 /* Handler for user request to terminate */
     84 void sighdl(int sig)
     85 {
     86 	do {
     87 		do_it = 0;
     88 	}
     89 	while (do_it);
     90 }
     91 
     92 long long canceled, ended;
     93 
     94 /* The canceled thread */
     95 void *th(void *arg)
     96 {
     97 	int ret = 0;
     98 	ret = pthread_barrier_wait(arg);
     99 
    100 	if ((ret != 0) && (ret != PTHREAD_BARRIER_SERIAL_THREAD)) {
    101 		UNRESOLVED(ret, "Failed to wait for the barrier");
    102 	}
    103 
    104 	return NULL;
    105 }
    106 
    107 /* Thread function */
    108 void *threaded(void *arg)
    109 {
    110 	int ret = 0;
    111 	pthread_t child;
    112 
    113 	/* Initialize the barrier */
    114 	ret = pthread_barrier_init(arg, NULL, 2);
    115 
    116 	if (ret != 0) {
    117 		UNRESOLVED(ret, "Failed to initialize a barrier");
    118 	}
    119 
    120 	while (do_it) {
    121 		/* Create the thread */
    122 		ret = pthread_create(&child, NULL, th, arg);
    123 
    124 		if (ret != 0) {
    125 			UNRESOLVED(ret, "Thread creation failed");
    126 		}
    127 
    128 		/* Synchronize */
    129 		ret = pthread_barrier_wait(arg);
    130 
    131 		if ((ret != 0) && (ret != PTHREAD_BARRIER_SERIAL_THREAD)) {
    132 			UNRESOLVED(ret, "Failed to wait for the barrier");
    133 		}
    134 
    135 		/* Cancel the thread */
    136 		ret = pthread_cancel(child);
    137 
    138 		if (ret == 0)
    139 			canceled++;
    140 		else
    141 			ended++;
    142 
    143 		/* Join the thread */
    144 		ret = pthread_join(child, NULL);
    145 
    146 		if (ret != 0) {
    147 			UNRESOLVED(ret, "Unable to join the child");
    148 		}
    149 
    150 	}
    151 
    152 	/* Destroy the barrier */
    153 	ret = pthread_barrier_destroy(arg);
    154 
    155 	if (ret != 0) {
    156 		UNRESOLVED(ret, "Failed to destroy a barrier");
    157 	}
    158 
    159 	return NULL;
    160 }
    161 
    162 /* Main function */
    163 int main(int argc, char *argv[])
    164 {
    165 	int ret = 0, i;
    166 
    167 	struct sigaction sa;
    168 
    169 	pthread_t th[NTHREADS];
    170 	pthread_barrier_t b[NTHREADS];
    171 
    172 	/* Initialize output routine */
    173 	output_init();
    174 
    175 	/* Register the signal handler for SIGUSR1 */
    176 	sigemptyset(&sa.sa_mask);
    177 
    178 	sa.sa_flags = 0;
    179 
    180 	sa.sa_handler = sighdl;
    181 
    182 	if ((ret = sigaction(SIGUSR1, &sa, NULL))) {
    183 		UNRESOLVED(ret, "Unable to register signal handler");
    184 	}
    185 
    186 	if ((ret = sigaction(SIGALRM, &sa, NULL))) {
    187 		UNRESOLVED(ret, "Unable to register signal handler");
    188 	}
    189 #if VERBOSE > 1
    190 	output("[parent] Signal handler registered\n");
    191 
    192 #endif
    193 
    194 	for (i = 0; i < NTHREADS; i++) {
    195 		ret = pthread_create(&th[i], NULL, threaded, &b[i]);
    196 
    197 		if (ret != 0) {
    198 			UNRESOLVED(ret, "Failed to create a thread");
    199 		}
    200 	}
    201 
    202 #if VERBOSE > 1
    203 	output("[parent] All threads are running\n");
    204 
    205 #endif
    206 
    207 	/* Then join */
    208 	for (i = 0; i < NTHREADS; i++) {
    209 		ret = pthread_join(th[i], NULL);
    210 
    211 		if (ret != 0) {
    212 			UNRESOLVED(ret, "Failed to join a thread");
    213 		}
    214 	}
    215 
    216 	/* We've been asked to stop */
    217 
    218 	output("pthread_cancel stress test PASSED\n");
    219 
    220 	output(" - %llu threads canceled\n", canceled);
    221 
    222 	output(" - %llu threads ended\n", ended);
    223 
    224 	PASSED;
    225 }
    226