Home | History | Annotate | Download | only in sigaction
      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 * This sample test aims to check the following assertions:
     18 *
     19 * If SA_NODEFER is not set in sa_flags, the caught signal is added to the
     20 * thread's signal mask during the handler execution.
     21 
     22 * The steps are:
     23 * -> register a signal handler for SIGINT
     24 * -> raise SIGINT
     25 * -> In handler, check for reentrance then raise SIGINT again.
     26 
     27 * The test fails if signal handler if reentered or signal is not pending when raised again.
     28 */
     29 
     30 /* We are testing conformance to IEEE Std 1003.1, 2003 Edition */
     31 #define _POSIX_C_SOURCE 200112L
     32 
     33 /******************************************************************************/
     34 /*************************** standard includes ********************************/
     35 /******************************************************************************/
     36 #include <pthread.h>
     37 #include <stdarg.h>
     38 #include <stdio.h>
     39 #include <stdlib.h>
     40 #include <string.h>
     41 #include <unistd.h>
     42 
     43 #include <signal.h>
     44 #include <errno.h>
     45 
     46 /******************************************************************************/
     47 /***************************   Test framework   *******************************/
     48 /******************************************************************************/
     49 #include "../testfrmw/testfrmw.h"
     50 #include "../testfrmw/testfrmw.c"
     51 /* This header is responsible for defining the following macros:
     52  * UNRESOLVED(ret, descr);
     53  *    where descr is a description of the error and ret is an int
     54  *   (error code for example)
     55  * FAILED(descr);
     56  *    where descr is a short text saying why the test has failed.
     57  * PASSED();
     58  *    No parameter.
     59  *
     60  * Both three macros shall terminate the calling process.
     61  * The testcase shall not terminate in any other maneer.
     62  *
     63  * The other file defines the functions
     64  * void output_init()
     65  * void output(char * string, ...)
     66  *
     67  * Those may be used to output information.
     68  */
     69 
     70 /******************************************************************************/
     71 /**************************** Configuration ***********************************/
     72 /******************************************************************************/
     73 #ifndef VERBOSE
     74 #define VERBOSE 1
     75 #endif
     76 
     77 #define SIGNAL SIGINT
     78 
     79 /******************************************************************************/
     80 /***************************    Test case   ***********************************/
     81 /******************************************************************************/
     82 
     83 int called = 0;
     84 
     85 void handler(int sig)
     86 {
     87 	int ret;
     88 	sigset_t pending;
     89 	called++;
     90 
     91 	if (called == 2) {
     92 		FAILED("Signal was not masked in signal handler");
     93 	}
     94 
     95 	if (called == 1) {
     96 
     97 		/* Raise the signal again. It should be masked */
     98 		ret = raise(SIGNAL);
     99 
    100 		if (ret != 0) {
    101 			UNRESOLVED(ret, "Failed to raise SIGINT again");
    102 		}
    103 
    104 		/* check the signal is pending */
    105 		ret = sigpending(&pending);
    106 
    107 		if (ret != 0) {
    108 			UNRESOLVED(ret, "Failed to get pending signal set");
    109 		}
    110 
    111 		ret = sigismember(&pending, SIGNAL);
    112 
    113 		if (ret != 1) {
    114 			FAILED("signal is not pending");
    115 		}
    116 	}
    117 
    118 	called++;
    119 }
    120 
    121 /* main function */
    122 int main(void)
    123 {
    124 	int ret;
    125 
    126 	struct sigaction sa;
    127 
    128 	/* Initialize output */
    129 	output_init();
    130 
    131 	/* Set the signal handler */
    132 	sa.sa_flags = 0;
    133 
    134 	sa.sa_handler = handler;
    135 
    136 	ret = sigemptyset(&sa.sa_mask);
    137 
    138 	if (ret != 0) {
    139 		UNRESOLVED(ret, "Failed to empty signal set");
    140 	}
    141 
    142 	/* Install the signal handler for SIGINT */
    143 	ret = sigaction(SIGNAL, &sa, 0);
    144 
    145 	if (ret != 0) {
    146 		UNRESOLVED(ret, "Failed to set signal handler");
    147 	}
    148 
    149 	ret = raise(SIGNAL);
    150 
    151 	if (ret != 0) {
    152 		UNRESOLVED(ret, "Failed to raise SIGINT");
    153 	}
    154 
    155 	while (called != 4)
    156 		sched_yield();
    157 
    158 	/* Test passed */
    159 #if VERBOSE > 0
    160 
    161 	output("Test passed\n");
    162 
    163 #endif
    164 
    165 	PASSED;
    166 }
    167