1/* 2* Copyright (c) 2005, 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 assertions: 19* 20* If SA_RESTART is set in sa_flags, interruptible function interrupted by signal 21* shall restart silently. 22 23* The steps are: 24* -> create a child thread 25* -> child registers a handler for SIGVTALRM with SA_RESTART, then waits for the semaphore 26* -> parent kills the child with SIGVTALRM, then post the semaphore. 27 28* The test fails if the sem_wait function returns EINTR 29 30*Note: 31This test uses sem_wait to check if EINTR is returned. As the function is not required to 32fail with EINTR, the test may return PASS and the feature not be correct (false positive). 33Anyway, a false negative status cannot be returned. 34 35*/ 36 37 38/* We are testing conformance to IEEE Std 1003.1, 2003 Edition */ 39#define _POSIX_C_SOURCE 200112L 40 41/* This test tests for an XSI feature */ 42#define _XOPEN_SOURCE 600 43 44/******************************************************************************/ 45/*************************** standard includes ********************************/ 46/******************************************************************************/ 47#include <pthread.h> 48#include <stdarg.h> 49#include <stdio.h> 50#include <stdlib.h> 51#include <string.h> 52#include <unistd.h> 53 54#include <semaphore.h> 55#include <signal.h> 56#include <errno.h> 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 66 * (error code for example) 67 * FAILED(descr); 68 * where descr is a short text saying why the test has failed. 69 * PASSED(); 70 * No parameter. 71 * 72 * Both three macros shall terminate the calling process. 73 * The testcase shall not terminate in any other maneer. 74 * 75 * The other file defines the functions 76 * void output_init() 77 * void output(char * string, ...) 78 * 79 * Those may be used to output information. 80 */ 81 82/******************************************************************************/ 83/**************************** Configuration ***********************************/ 84/******************************************************************************/ 85#ifndef VERBOSE 86#define VERBOSE 1 87#endif 88 89#define SIGNAL SIGVTALRM 90 91/******************************************************************************/ 92/*************************** Test case ***********************************/ 93/******************************************************************************/ 94 95volatile sig_atomic_t caught = 0; 96sem_t sem; 97 98/* Handler function */ 99void handler( int signo ) 100{ 101 printf( "Caught signal %d\n", signo ); 102 caught++; 103} 104 105/* Thread function */ 106void * threaded ( void * arg ) 107{ 108 int ret = 0; 109 110 ret = sem_wait( &sem ); 111 112 if ( ret != 0 ) 113 { 114 if ( errno == EINTR ) 115 { 116 FAILED( "The function returned EINTR while SA_RESTART is set" ); 117 } 118 else 119 { 120 UNRESOLVED( errno, "sem_wait failed" ); 121 } 122 } 123 124 return NULL; 125} 126 127/* main function */ 128int main() 129{ 130 int ret; 131 pthread_t child; 132 133 134 struct sigaction sa; 135 136 /* Initialize output */ 137 output_init(); 138 139 /* Set the signal handler */ 140 sa.sa_flags = SA_RESTART; 141 sa.sa_handler = handler; 142 ret = sigemptyset( &sa.sa_mask ); 143 144 if ( ret != 0 ) 145 { 146 UNRESOLVED( ret, "Failed to empty signal set" ); 147 } 148 149 /* Install the signal handler for SIGNAL */ 150 ret = sigaction( SIGNAL, &sa, 0 ); 151 152 if ( ret != 0 ) 153 { 154 UNRESOLVED( ret, "Failed to set signal handler" ); 155 } 156 157 /* Initialize the semaphore */ 158 ret = sem_init( &sem, 0, 0 ); 159 160 if ( ret != 0 ) 161 { 162 UNRESOLVED( ret, "Failed to init a semaphore" ); 163 } 164 165 /* Create the child thread */ 166 ret = pthread_create( &child, NULL, threaded, NULL ); 167 168 if ( ret != 0 ) 169 { 170 UNRESOLVED( ret, "Failed to create a child thread" ); 171 } 172 173 /* Let the child thread enter the wait routine... 174 we use sched_yield as there is no certain way to test that the child 175 is waiting for the semaphore... */ 176 sched_yield(); 177 178 sched_yield(); 179 180 sched_yield(); 181 182 /* Ok, now kill the child */ 183 ret = pthread_kill( child, SIGNAL ); 184 185 if ( ret != 0 ) 186 { 187 UNRESOLVED( ret, "Failed to kill the child thread" ); 188 } 189 190 /* wait that the child receives the signal */ 191 while ( !caught ) 192 sched_yield(); 193 194 /* Now let the child run and terminate */ 195 ret = sem_post( &sem ); 196 197 if ( ret != 0 ) 198 { 199 UNRESOLVED( errno, "Failed to post the semaphore" ); 200 } 201 202 ret = pthread_join( child, NULL ); 203 204 if ( ret != 0 ) 205 { 206 UNRESOLVED( ret, "Failed to join the thread" ); 207 } 208 209 /* terminate */ 210 ret = sem_destroy( &sem ); 211 212 if ( ret != 0 ) 213 { 214 UNRESOLVED( ret, "Failed to destroy the semaphore" ); 215 } 216 217 218 /* Test passed */ 219#if VERBOSE > 0 220 221 output( "Test passed\n" ); 222 223#endif 224 225 PASSED; 226} 227