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 child process is created with no pending signal 21 22* The steps are: 23* -> block SIGUSR1 and SIGUSR2 24* -> send those signals and wait they are pending 25* -> fork 26* -> check the signals are blocked but not pending in the new process. 27 28* The test fails if the signals are pending or if 29* they are not blocked (this counters assertion 2). 30 31*/ 32 33 34/* We are testing conformance to IEEE Std 1003.1, 2003 Edition */ 35#define _POSIX_C_SOURCE 200112L 36 37/********************************************************************************************/ 38/****************************** standard includes *****************************************/ 39/********************************************************************************************/ 40#include <pthread.h> 41 #include <stdarg.h> 42 #include <stdio.h> 43 #include <stdlib.h> 44 #include <string.h> 45 #include <unistd.h> 46 47#include <sys/wait.h> 48 #include <errno.h> 49 50#include <signal.h> 51 52/********************************************************************************************/ 53/****************************** Test framework *****************************************/ 54/********************************************************************************************/ 55#include "testfrmw.h" 56 #include "testfrmw.c" 57/* This header is responsible for defining the following macros: 58 * UNRESOLVED(ret, descr); 59 * where descr is a description of the error and ret is an int (error code for example) 60 * FAILED(descr); 61 * where descr is a short text saying why the test has failed. 62 * PASSED(); 63 * No parameter. 64 * 65 * Both three macros shall terminate the calling process. 66 * The testcase shall not terminate in any other maneer. 67 * 68 * The other file defines the functions 69 * void output_init() 70 * void output(char * string, ...) 71 * 72 * Those may be used to output information. 73 */ 74 75/********************************************************************************************/ 76/********************************** Configuration ******************************************/ 77/********************************************************************************************/ 78#ifndef VERBOSE 79#define VERBOSE 1 80#endif 81 82/********************************************************************************************/ 83/*********************************** Test case *****************************************/ 84/********************************************************************************************/ 85 86/* The main test function. */ 87int main( int argc, char * argv[] ) 88{ 89 int ret, status; 90 pid_t child, ctl; 91 92 sigset_t mask, pending; 93 94 /* Initialize output */ 95 output_init(); 96 97 /* block SIGUSR1 and SIGUSR2 */ 98 ret = sigemptyset( &mask ); 99 100 if ( ret != 0 ) 101 { 102 UNRESOLVED( errno, "Failed to initialize signal set" ); 103 } 104 105 ret = sigaddset( &mask, SIGUSR1 ); 106 107 if ( ret != 0 ) 108 { 109 UNRESOLVED( errno, "Failed to add SIGUSR1 to signal set" ); 110 } 111 112 ret = sigaddset( &mask, SIGUSR2 ); 113 114 if ( ret != 0 ) 115 { 116 UNRESOLVED( errno, "Failed to add SIGUSR2 to signal set" ); 117 } 118 119 ret = sigprocmask( SIG_BLOCK, &mask, NULL ); 120 121 if ( ret != 0 ) 122 { 123 UNRESOLVED( errno, "Sigprocmask failed" ); 124 } 125 126 /* Make the signals pending */ 127 ret = kill( getpid(), SIGUSR1 ); 128 129 if ( ret != 0 ) 130 { 131 UNRESOLVED( errno, "failed to kill with SIGUSR1" ); 132 } 133 134 ret = kill( getpid(), SIGUSR2 ); 135 136 if ( ret != 0 ) 137 { 138 UNRESOLVED( errno, "failed to kill with SIGUSR2" ); 139 } 140 141 do 142 { 143 ret = sigpending( &pending ); 144 145 if ( ret != 0 ) 146 { 147 UNRESOLVED( errno, "failed to examine pending signal set" ); 148 } 149 150 ret = sigismember( &pending, SIGUSR1 ); 151 152 if ( ret < 0 ) 153 { 154 UNRESOLVED( errno, "Unable to check signal USR1 presence" ); 155 } 156 157 if ( ret == 1 ) 158 { 159 ret = sigismember( &pending, SIGUSR2 ); 160 161 if ( ret < 0 ) 162 { 163 UNRESOLVED( errno, "Unable to check signal USR2 presence" ); 164 } 165 } 166 } 167 while ( ret != 1 ); 168 169#if VERBOSE > 0 170 171 output( "SIGUSR1 and SIGUSR2 are pending, we can fork\n" ); 172 173#endif 174 175 /* Create the child */ 176 child = fork(); 177 178 if ( child == ( pid_t ) - 1 ) 179 { 180 UNRESOLVED( errno, "Failed to fork" ); 181 } 182 183 /* child */ 184 if ( child == ( pid_t ) 0 ) 185 { 186 /* Examine the current blocked signal set. USR1 & USR2 shall be present */ 187 ret = sigprocmask( 0, NULL, &mask ); 188 189 if ( ret != 0 ) 190 { 191 UNRESOLVED( errno, "Sigprocmask failed in child" ); 192 } 193 194 ret = sigismember( &mask, SIGUSR1 ); 195 196 if ( ret < 0 ) 197 { 198 UNRESOLVED( errno, "Unable to check signal USR1 presence" ); 199 } 200 201 if ( ret == 0 ) 202 { 203 FAILED( "The new process does not mask SIGUSR1 as its parent" ); 204 } 205 206 ret = sigismember( &mask, SIGUSR2 ); 207 208 if ( ret < 0 ) 209 { 210 UNRESOLVED( errno, "Unable to check signal USR2 presence" ); 211 } 212 213 if ( ret == 0 ) 214 { 215 FAILED( "The new process does not mask SIGUSR2 as its parent" ); 216 } 217 218#if VERBOSE > 0 219 output( "SIGUSR1 and SIGUSR2 are blocked in child\n" ); 220 221#endif 222 223 /* Examine pending signals */ 224 ret = sigpending( &pending ); 225 226 if ( ret != 0 ) 227 { 228 UNRESOLVED( errno, "failed to examine pending signal set in child" ); 229 } 230 231 ret = sigismember( &pending, SIGUSR1 ); 232 233 if ( ret < 0 ) 234 { 235 UNRESOLVED( errno, "Unable to check signal USR1 presence" ); 236 } 237 238 if ( ret != 0 ) 239 { 240 FAILED( "The new process was created with SIGUSR1 pending" ); 241 } 242 243 ret = sigismember( &pending, SIGUSR2 ); 244 245 if ( ret < 0 ) 246 { 247 UNRESOLVED( errno, "Unable to check signal USR2 presence" ); 248 } 249 250 if ( ret != 0 ) 251 { 252 FAILED( "The new process was created with SIGUSR2 pending" ); 253 } 254 255#if VERBOSE > 0 256 output( "SIGUSR1 and SIGUSR2 are not pending in child\n" ); 257 258#endif 259 260 /* We're done */ 261 exit( PTS_PASS ); 262 } 263 264 /* Parent joins the child */ 265 ctl = waitpid( child, &status, 0 ); 266 267 if ( ctl != child ) 268 { 269 UNRESOLVED( errno, "Waitpid returned the wrong PID" ); 270 } 271 272 if ( ( !WIFEXITED( status ) ) || ( WEXITSTATUS( status ) != PTS_PASS ) ) 273 { 274 FAILED( "Child exited abnormally" ); 275 } 276 277 /* Test passed */ 278#if VERBOSE > 0 279 280 output( "Test passed\n" ); 281 282#endif 283 284 PASSED; 285} 286 287 288