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 sample test aims to check the following assertion: 19 * 20 * The new thread inherits is signal mask from the calling thread, 21 * and has no pending signal at creation time. 22 23 * The steps are: 24 * 1. In main(), create a signal mask with a few signals in the set (SIGUSR1 and SIGUSR2). 25 * 2. Raise those signals in main. These signals now should be pending. 26 * 3. Create a thread using pthread_create(). 27 * 4. The thread should have the same signal mask, but no signals should be pending. 28 29 * Parts of this test are copied from 8-1.c (author: rolla.n.selbak REMOVE-THIS AT intel DOT com) 30 */ 31 32 33 /* We are testing conformance to IEEE Std 1003.1, 2003 Edition */ 34 #define _POSIX_C_SOURCE 200112L 35 36 /* Some routines are part of the XSI Extensions */ 37#ifndef WITHOUT_XOPEN 38 #define _XOPEN_SOURCE 600 39#endif 40/********************************************************************************************/ 41/****************************** standard includes *****************************************/ 42/********************************************************************************************/ 43 #include <pthread.h> 44 #include <stdarg.h> 45 #include <stdio.h> 46 #include <stdlib.h> 47 #include <string.h> 48 #include <unistd.h> 49 50 #include <sched.h> 51 #include <semaphore.h> 52 #include <errno.h> 53 #include <assert.h> 54 #include <sys/wait.h> 55 #include <signal.h> 56 57 58/********************************************************************************************/ 59/****************************** Test framework *****************************************/ 60/********************************************************************************************/ 61 #include "testfrmw.h" 62 #include "testfrmw.c" 63 /* This header is responsible for defining the following macros: 64 * UNRESOLVED(ret, descr); 65 * where descr is a description of the error and ret is an int (error code for example) 66 * FAILED(descr); 67 * where descr is a short text saying why the test has failed. 68 * PASSED(); 69 * No parameter. 70 * 71 * Both three macros shall terminate the calling process. 72 * The testcase shall not terminate in any other maneer. 73 * 74 * The other file defines the functions 75 * void output_init() 76 * void output(char * string, ...) 77 * 78 * Those may be used to output information. 79 */ 80 81/********************************************************************************************/ 82/********************************** Configuration ******************************************/ 83/********************************************************************************************/ 84#ifndef VERBOSE 85#define VERBOSE 1 86#endif 87 88/********************************************************************************************/ 89/*********************************** Test cases *****************************************/ 90/********************************************************************************************/ 91 92#include "threads_scenarii.c" 93 94/* This file will define the following objects: 95 * scenarii: array of struct __scenario type. 96 * NSCENAR : macro giving the total # of scenarii 97 * scenar_init(): function to call before use the scenarii array. 98 * scenar_fini(): function to call after end of use of the scenarii array. 99 */ 100 101 102/********************************************************************************************/ 103/*********************************** Real Test *****************************************/ 104/********************************************************************************************/ 105 106typedef struct 107{ 108 sigset_t mask; 109 sigset_t pending; 110} testdata_t; 111 112 113/* Thread function; which will check the signal mask and pending signals */ 114void * threaded(void * arg) 115{ 116 int ret; 117 testdata_t * td=(testdata_t *)arg; 118 119 /* Obtain the signal mask of this thread. */ 120 ret = pthread_sigmask(SIG_SETMASK, NULL, &(td->mask)); 121 if (ret != 0) { UNRESOLVED(ret, "Failed to get the signal mask of the thread"); } 122 123 /* Obtain the pending signals of this thread. It should be empty. */ 124 ret = sigpending(&(td->pending)); 125 if (ret != 0) { UNRESOLVED(errno, "Failed to get pending signals from the thread"); } 126 127 /* Signal we're done (especially in case of a detached thread) */ 128 do { ret = sem_post(&scenarii[sc].sem); } 129 while ((ret == -1) && (errno == EINTR)); 130 if (ret == -1) { UNRESOLVED(errno, "Failed to wait for the semaphore"); } 131 132 /* return */ 133 return arg; 134} 135 136int main (int argc, char *argv[]) 137{ 138 int ret=0; 139 pthread_t child; 140 141 testdata_t td_parent, td_thread; 142 143 /* Initialize output routine */ 144 output_init(); 145 146 /* Initialize thread attribute objects */ 147 scenar_init(); 148 149 /* Initialize the signal state */ 150 ret = sigemptyset(&(td_parent.mask)); 151 if (ret != 0) { UNRESOLVED(ret, "Failed to initialize a signal set"); } 152 153 ret = sigemptyset(&(td_parent.pending)); 154 if (ret != 0) { UNRESOLVED(ret, "Failed to initialize a signal set"); } 155 156 /* Add SIGCONT, SIGUSR1 and SIGUSR2 to the set of blocked signals */ 157 ret = sigaddset(&(td_parent.mask), SIGUSR1); 158 if (ret != 0) { UNRESOLVED(ret, "Failed to add SIGUSR1 to the signal set"); } 159 160 ret = sigaddset(&(td_parent.mask), SIGUSR2); 161 if (ret != 0) { UNRESOLVED(ret, "Failed to add SIGUSR2 to the signal set"); } 162 163 /* Block those signals. */ 164 ret = pthread_sigmask(SIG_SETMASK, &(td_parent.mask), NULL); 165 if (ret != 0) { UNRESOLVED(ret, "Failed to mask the singals in main"); } 166 167 /* Raise those signals so they are now pending. */ 168 ret = raise(SIGUSR1); 169 if (ret != 0) { UNRESOLVED(errno, "Failed to raise SIGUSR1"); } 170 ret = raise(SIGUSR2); 171 if (ret != 0) { UNRESOLVED(errno, "Failed to raise SIGUSR2"); } 172 173 /* Do the testing for each thread */ 174 for (sc=0; sc < NSCENAR; sc++) 175 { 176 #if VERBOSE > 0 177 output("-----\n"); 178 output("Starting test with scenario (%i): %s\n", sc, scenarii[sc].descr); 179 #endif 180 181 /* (re)initialize thread signal sets */ 182 ret = sigemptyset(&(td_thread.mask)); 183 if (ret != 0) { UNRESOLVED(ret, "Failed to initialize a signal set"); } 184 185 ret = sigemptyset(&(td_thread.pending)); 186 if (ret != 0) { UNRESOLVED(ret, "Failed to initialize a signal set"); } 187 188 189 ret = pthread_create(&child, &scenarii[sc].ta, threaded, &td_thread); 190 switch (scenarii[sc].result) 191 { 192 case 0: /* Operation was expected to succeed */ 193 if (ret != 0) { UNRESOLVED(ret, "Failed to create this thread"); } 194 break; 195 196 case 1: /* Operation was expected to fail */ 197 if (ret == 0) { UNRESOLVED(-1, "An error was expected but the thread creation succeeded"); } 198 break; 199 200 case 2: /* We did not know the expected result */ 201 default: 202 #if VERBOSE > 0 203 if (ret == 0) 204 { output("Thread has been created successfully for this scenario\n"); } 205 else 206 { output("Thread creation failed with the error: %s\n", strerror(ret)); } 207 #endif 208 } 209 if (ret == 0) /* The new thread is running */ 210 { 211 if (scenarii[sc].detached == 0) 212 { 213 ret = pthread_join(child, NULL); 214 if (ret != 0) { UNRESOLVED(ret, "Unable to join a thread"); } 215 } 216 else 217 { 218 /* Just wait for the thread to terminate */ 219 do { ret = sem_wait(&scenarii[sc].sem); } 220 while ((ret == -1) && (errno == EINTR)); 221 if (ret == -1) { UNRESOLVED(errno, "Failed to wait for the semaphore"); } 222 } 223 224 /* The thread has terminated its work, so we can now control */ 225 ret = sigismember(&(td_thread.mask), SIGUSR1); 226 if (ret != 1) 227 { 228 if (ret == 0) { FAILED("The thread did not inherit the signal mask"); } 229 /* else */ 230 UNRESOLVED(ret, "sigismember() failed"); 231 } 232 233 ret = sigismember(&(td_thread.mask), SIGUSR2); 234 if (ret != 1) 235 { 236 if (ret == 0) { FAILED("The thread did not inherit the signal mask"); } 237 /* else */ 238 UNRESOLVED(ret, "sigismember() failed"); 239 } 240 241 ret = sigismember(&(td_thread.pending), SIGUSR1); 242 if (ret != 0) 243 { 244 if (ret == 1) { FAILED("The thread inherited the pending signal SIGUSR1"); } 245 /* else */ 246 UNRESOLVED(ret, "sigismember() failed"); 247 } 248 249 ret = sigismember(&(td_thread.pending), SIGUSR2); 250 if (ret != 0) 251 { 252 if (ret == 1) { FAILED("The thread inherited the pending signal SIGUSR2"); } 253 /* else */ 254 UNRESOLVED(ret, "sigismember() failed"); 255 } 256 257 258 } 259 } 260 261 scenar_fini(); 262 #if VERBOSE > 0 263 output("-----\n"); 264 output("All test data destroyed\n"); 265 output("Test PASSED\n"); 266 #endif 267 268 PASSED; 269} 270 271