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_SIGINFO is set and realtime signals extension is supported, queueable
     20 * signals generated by sigqueue or some other functions are delivered in FIFO
     21 * order.
     22 
     23 * The steps are:
     24 * -> Test for RTS extension support
     25 * -> install a handler for SIGRTMAX signal with SA_SIGINFO set.
     26 * -> Mask this signal
     27 * -> Generate the signal several imes with sigqueue and known user values.
     28 * -> unmask the signal
     29 * -> check that the signals are delivered in order.
     30 
     31 * The test fails if the signals are not delivered in FIFO order.
     32 */
     33 
     34 /* We are testing conformance to IEEE Std 1003.1, 2003 Edition */
     35 #define _POSIX_C_SOURCE 200112L
     36 
     37 /* This test uses some XSI features */
     38 //#define _XOPEN_SOURCE 600
     39 
     40 /******************************************************************************/
     41 /*************************** standard includes ********************************/
     42 /******************************************************************************/
     43 #include <pthread.h>
     44 #include <stdarg.h>
     45 #include <stdio.h>
     46 #include <stdlib.h>
     47 #include <string.h>
     48 #include <unistd.h>
     49 
     50 #include <signal.h>
     51 #include <errno.h>
     52 
     53 /******************************************************************************/
     54 /***************************   Test framework   *******************************/
     55 /******************************************************************************/
     56 #include "../testfrmw/testfrmw.h"
     57 #include "../testfrmw/testfrmw.c"
     58 /* This header is responsible for defining the following macros:
     59  * UNRESOLVED(ret, descr);
     60  *    where descr is a description of the error and ret is an int
     61  *   (error code for example)
     62  * FAILED(descr);
     63  *    where descr is a short text saying why the test has failed.
     64  * PASSED();
     65  *    No parameter.
     66  *
     67  * Both three macros shall terminate the calling process.
     68  * The testcase shall not terminate in any other maneer.
     69  *
     70  * The other file defines the functions
     71  * void output_init()
     72  * void output(char * string, ...)
     73  *
     74  * Those may be used to output information.
     75  */
     76 
     77 /******************************************************************************/
     78 /**************************** Configuration ***********************************/
     79 /******************************************************************************/
     80 #ifndef VERBOSE
     81 #define VERBOSE 1
     82 #endif
     83 
     84 #define QUEUELENGTH 10
     85 
     86 /******************************************************************************/
     87 /***************************    Test case   ***********************************/
     88 /******************************************************************************/
     89 
     90 sig_atomic_t latest = 0;
     91 
     92 void handler(int sig, siginfo_t * info, void *context)
     93 {
     94 	if (info->si_signo != SIGRTMAX) {
     95 		output("Received unexpected signal %d\n", info->si_signo);
     96 	} else {
     97 		latest++;
     98 
     99 		if (latest != info->si_value.sival_int) {
    100 			output("Got signal %d, expected %d!\n",
    101 			       info->si_value.sival_int, latest);
    102 			FAILED("Wrong signal delivered -- no FIFO order?");
    103 		}
    104 	}
    105 }
    106 
    107 /* main function */
    108 int main(void)
    109 {
    110 	int ret;
    111 	long rts;
    112 
    113 	struct sigaction sa;
    114 	union sigval sv;
    115 	sigset_t mask;
    116 
    117 	/* Initialize output */
    118 	output_init();
    119 
    120 	/* Test the RTS extension */
    121 	rts = sysconf(_SC_REALTIME_SIGNALS);
    122 
    123 	if (rts < 0L) {
    124 		UNTESTED("This test needs the RTS extension");
    125 	}
    126 
    127 	/* Set the signal handler */
    128 	sa.sa_flags = SA_SIGINFO;
    129 
    130 	sa.sa_sigaction = handler;
    131 
    132 	ret = sigemptyset(&sa.sa_mask);
    133 
    134 	if (ret != 0) {
    135 		UNRESOLVED(ret, "Failed to empty signal set");
    136 	}
    137 
    138 	/* Install the signal handler for SIGRTMAX */
    139 	ret = sigaction(SIGRTMAX, &sa, 0);
    140 
    141 	if (ret != 0) {
    142 		UNRESOLVED(ret, "Failed to set signal handler");
    143 	}
    144 
    145 	/* Mask this signal */
    146 	ret = sigemptyset(&mask);
    147 
    148 	if (ret != 0) {
    149 		UNRESOLVED(ret, "An error occured while initializing mask");
    150 	}
    151 
    152 	ret = sigaddset(&mask, SIGRTMAX);
    153 
    154 	if (ret != 0) {
    155 		UNRESOLVED(ret, "Failed to add SIGRTMAX to signal set");
    156 	}
    157 
    158 	ret = sigprocmask(SIG_BLOCK, &mask, NULL);
    159 
    160 	if (ret != 0) {
    161 		UNRESOLVED(ret, "Failed to set process signal mask");
    162 	}
    163 
    164 	/* Now queue the signal to be pending */
    165 
    166 	for (sv.sival_int = 1; sv.sival_int <= QUEUELENGTH; sv.sival_int++) {
    167 		ret = sigqueue(getpid(), SIGRTMAX, sv);
    168 
    169 		if (ret != 0) {
    170 			UNRESOLVED(ret, "Failed to queue the signal");
    171 		}
    172 	}
    173 
    174 	if (latest != 0) {
    175 		FAILED("Signal was delivered while masked??");
    176 	}
    177 
    178 	/* And finally unmask the signal so it is delivered */
    179 	ret = sigprocmask(SIG_UNBLOCK, &mask, NULL);
    180 
    181 	if (ret != 0) {
    182 		UNRESOLVED(ret, "Failed to set process signal mask");
    183 	}
    184 
    185 	sched_yield();
    186 
    187 	/* Check the signal has been delivered as expected */
    188 
    189 	if (latest != QUEUELENGTH) {
    190 		output("Only %d signal delivered instead of %d\n", latest,
    191 		       QUEUELENGTH);
    192 
    193 		if (latest == 1) {
    194 			UNTESTED
    195 			    ("It seems like SIGRTMAX is not a queuable signal here?");
    196 		}
    197 	}
    198 
    199 	/* Test passed */
    200 #if VERBOSE > 0
    201 
    202 	output("Test passed\n");
    203 
    204 #endif
    205 
    206 	PASSED;
    207 }
    208