Home | History | Annotate | Download | only in templates
      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.,
     15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 %%MYSIG%% with SA_RESTART, then waits for the semaphore
     26 * -> parent kills the child with %%MYSIG%%, then post the semaphore.
     27 
     28 * The test fails if the sem_wait function returns EINTR
     29 
     30 *Note:
     31 This test uses sem_wait to check if EINTR is returned. As the function is not required to
     32 fail with EINTR, the test may return PASS and the feature not be correct (false positive).
     33 Anyway, 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 %%MYSIG%%
     90 
     91 /******************************************************************************/
     92 /***************************    Test case   ***********************************/
     93 /******************************************************************************/
     94 
     95 volatile sig_atomic_t caught = 0;
     96 sem_t sem;
     97 
     98 /* Handler function */
     99 void handler( int signo )
    100 {
    101 	printf( "Caught signal %d\n", signo );
    102 	caught++;
    103 }
    104 
    105 /* Thread function */
    106 void * 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 */
    128 int 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