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 per-process timers are not inherited. 21 22* The steps are: 23* -> Create a per-process timer 24* -> fork 25* -> check if the timer exists in child. 26 27* The test fails if the timer expires in child (timer signal is delivered). 28 29*/ 30 31 32/* We are testing conformance to IEEE Std 1003.1, 2003 Edition */ 33#define _POSIX_C_SOURCE 200112L 34 35/********************************************************************************************/ 36/****************************** standard includes *****************************************/ 37/********************************************************************************************/ 38#include <pthread.h> 39 #include <stdarg.h> 40 #include <stdio.h> 41 #include <stdlib.h> 42 #include <string.h> 43 #include <unistd.h> 44 45#include <sys/wait.h> 46 #include <errno.h> 47 48#include <signal.h> 49 #include <time.h> 50 51/********************************************************************************************/ 52/****************************** Test framework *****************************************/ 53/********************************************************************************************/ 54#include "testfrmw.h" 55 #include "testfrmw.c" 56/* This header is responsible for defining the following macros: 57 * UNRESOLVED(ret, descr); 58 * where descr is a description of the error and ret is an int (error code for example) 59 * FAILED(descr); 60 * where descr is a short text saying why the test has failed. 61 * PASSED(); 62 * No parameter. 63 * 64 * Both three macros shall terminate the calling process. 65 * The testcase shall not terminate in any other maneer. 66 * 67 * The other file defines the functions 68 * void output_init() 69 * void output(char * string, ...) 70 * 71 * Those may be used to output information. 72 */ 73 74/********************************************************************************************/ 75/********************************** Configuration ******************************************/ 76/********************************************************************************************/ 77#ifndef VERBOSE 78#define VERBOSE 1 79#endif 80 81/********************************************************************************************/ 82/*********************************** Test case *****************************************/ 83/********************************************************************************************/ 84 85/* Global control value */ 86int notified; 87 88/* Notification routine */ 89void notification( union sigval sv ) 90{ 91 if ( sv.sival_int != SIGUSR1 ) 92 { 93 output( "Got signal %d, expected %d\n", sv.sival_int, SIGUSR1 ); 94 UNRESOLVED( 1, "Unexpected notification" ); 95 } 96 97 notified = ( int ) getpid(); 98} 99 100/* The main test function. */ 101int main( int argc, char * argv[] ) 102{ 103 int ret, status; 104 pid_t child, ctl; 105 106 timer_t tmr; 107 108 struct sigevent se; 109 110 struct itimerspec it; 111 112 /* Initialize output */ 113 output_init(); 114 115 notified = 0; 116 117 /* Create the timer */ 118 se.sigev_notify = SIGEV_THREAD; 119 se.sigev_signo = 0; 120 se.sigev_value.sival_int = SIGUSR1; 121 se.sigev_notify_function = ¬ification; 122 se.sigev_notify_attributes = NULL; /* default detached thread */ 123 124 ret = timer_create( CLOCK_REALTIME, &se, &tmr ); 125 126 if ( ret != 0 ) 127 { 128 UNRESOLVED( errno, "Failed to create a timer" ); 129 } 130 131 /* Arm the timer */ 132 it.it_interval.tv_nsec = 0; 133 134 it.it_interval.tv_sec = 0; 135 136 it.it_value.tv_sec = 0; 137 138 it.it_value.tv_nsec = 500000000; /* 0.5 sec */ 139 140 ret = timer_settime( tmr, 0, &it, NULL ); 141 142 /* Create the child */ 143 child = fork(); 144 145 if ( child == ( pid_t ) - 1 ) 146 { 147 UNRESOLVED( errno, "Failed to fork" ); 148 } 149 150 /* child */ 151 if ( child == ( pid_t ) 0 ) 152 { 153 154 sleep( 1 ); 155 156 if ( notified != 0 ) 157 { 158 if ( notified == ( int ) getpid() ) 159 { 160 FAILED( "Per-Process Timer was inherited in child" ); 161 } 162 else 163 { 164 output( "Notification occured before the child forked" ); 165 } 166 } 167 168 /* We're done */ 169 exit( PTS_PASS ); 170 } 171 172 /* Parent joins the child */ 173 ctl = waitpid( child, &status, 0 ); 174 175 if ( ctl != child ) 176 { 177 UNRESOLVED( errno, "Waitpid returned the wrong PID" ); 178 } 179 180 if ( ( !WIFEXITED( status ) ) || ( WEXITSTATUS( status ) != PTS_PASS ) ) 181 { 182 FAILED( "Child exited abnormally" ); 183 } 184 185 if ( notified != ( int ) getpid() ) 186 { 187 output( "Notified value: %d\n", notified ); 188 UNRESOLVED( -1, "No notification occured -- per process timers do not work?" ); 189 } 190 191 /* Test passed */ 192#if VERBOSE > 0 193 output( "Test passed\n" ); 194 195#endif 196 PASSED; 197} 198 199