blob: e7de3e84b1d4d2458376d692a7e0a3440976a7cc [file] [log] [blame]
/*
* Copyright (C) Bull S.A. 1996
* Copyright (c) International Business Machines Corp., 2001
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*---------------------------------------------------------------------+
| signal_test_03 |
| ==================================================================== |
| |
| Description: Block a critical section from receiving signals. |
| |
| Algorithm: o Setup a signal-catching function |
| o Beginning of Critical section -- Set the process |
| signal mask to block the SIGILL signal |
| o Send SIGILL signal to the process to insure that |
| the signal is blocked during the critical section |
| o Preform the critical section code (merely sleep |
| for testing purposes) |
| o Verify that the signal was blocked |
| o End of Critical section -- unblock the signal and |
| suspend he process signal mask to unblock one |
| signal and suspend execution of the process until |
| the signal is received. Verify that the unblocked |
| signal is received. |
| |
| System calls: The following system calls are tested: |
| |
| sigsetmask () - Sets the current signal mask |
| sigblock () - Sets the current signal mask |
| sigvec () - Specify the action to take upon delivery |
| of a signal. |
| raise () - Sends a signal to the executing program |
| |
| Usage: signal_test_03 |
| |
| To compile: cc -o signal_test_03 signal_test_03 |
| |
| Last update: Ver. 1.2, 2/7/94 23:23:34 |
| |
| Change Activity |
| |
| Version Date Name Reason |
| 0.1 050689 CTU Initial version |
| 1.2 112293 DJK Rewrite for AIX version 4.1 |
| |
+---------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#define MASK(sig) (1 << ((sig) - 1))
#define MAXTIME 2 /* MAX timeout (minutes) */
#ifdef _LINUX_
// bits/signum.h defines _NSIG as 64
#define SIGMAX 64
#endif
#include "signals.h"
/* Function prototypes */
void handler (int);
void init_sig_vec ();
void sys_error (const char *, int);
void error (const char *, int);
/* Global variables */
int signals_received = 0;
/*---------------------------------------------------------------------+
| main () |
| ==================================================================== |
| |
| Function: Main program (see prolog for more details) |
| |
+---------------------------------------------------------------------*/
int main (int argc, char **argv)
{
int timeout = MAXTIME*60; /* Number sec to wait for signal */
/* Print out program header */
printf ("%s: IPC Signals TestSuite program\n\n", *argv);
/* Set up our signal handlers */
init_sig_vec ();
/*
* Critical section - block SIGILL signal
*
* Block the SIGILL interrupt from interrupting the process
* with the sigprocmask () system function call.
*
* Send the SIGILL interrupt to the process in an attempt to
* disrupt the critial section -- the signal should be blocked.
* Wait one second to insure that the signal has plenty of time
* to reach the process.
*/
#ifdef _LINUX_
sigset_t mask;
sigemptyset (&mask);
sigaddset (&mask, SIGILL);
sigprocmask (SIG_BLOCK, &mask, NULL);
#else
if (sigblock ( MASK (SIGILL) ) < 0)
sys_error ("sigblock failed", __LINE__);
#endif
printf ("\t(BEGIN) Critial section\n");
/* Critial section */
sleep (1);
/*
* End of critical section - ensure SIGILL signal was not received
*
* Check to insure that the signal handler has not caught any signals,
* and then unblock all of the signals with the sigsetmask system
* function call.
*/
if (signals_received > 0)
error ("received an unexpected signal during the critical section",
__LINE__);
printf ("\n\t(END) Critial section\n");
#ifdef _LINUX_
sigemptyset (&mask);
sigprocmask (SIG_SETMASK, &mask, NULL);
#else
if (sigsetmask (0) < 0)
sys_error ("sigsetmask failed", __LINE__);
#endif
raise (SIGILL);
/*
* Upon unblocking the signals, should receive the SIGILL signal.
* Verify that it indeed is caught.
*/
while (signals_received == 0 && --timeout)
{
printf(".");
fflush(stdout);
sleep (1);
}
if (timeout == 0)
error ("failed to receive SIGILL signal after unblocking signals",
__LINE__);
/* Program completed successfully -- exit */
printf ("\nsuccessful!\n");
return (0);
}
/*---------------------------------------------------------------------+
| init_sig_vec () |
| ==================================================================== |
| |
| Function: Initialize the signal vector for ALL possible signals |
| (as defined in /usr/include/sys/signal.h) except for |
| the following signals which cannot be caught or ignored: |
| |
| o SIGKILL (9) |
| o SIGSTOP (17) |
| o SIGCONT (19) |
| |
| Returns: Nothing |
| |
+---------------------------------------------------------------------*/
void init_sig_vec ()
{
struct sigaction invec;
char msg [256]; /* Buffer for error message */
int i;
for (i=1; i<=SIGMAX; i++) {
/* Cannot catch or ignore the following signals */
#ifdef _IA64 /* SIGWAITING not supported, RESERVED */
if ((i == SIGKILL) || (i == SIGSTOP) ||
(i == SIGCONT) || (i == SIGWAITING)) continue;
#else
# ifdef _LINUX_
if ((i == SIGKILL) || (i == SIGSTOP) || ((i>=32)&&(i<=34))) continue;
# else
if (i == SIGKILL || i == SIGSTOP || i == SIGCONT) continue;
# endif
#endif
invec.sa_handler = (void (*)(int)) handler;
sigemptyset (&invec.sa_mask);
invec.sa_flags = 0;
if (sigaction (i, &invec, (struct sigaction *) NULL) < 0) {
sprintf (msg, "sigaction failed on signal %d", i);
error (msg, __LINE__);
}
}
}
/*---------------------------------------------------------------------+
| handler () |
| ==================================================================== |
| |
| Function: Signal catching function. This function is called each |
| time a non-blocked signal is received by the process. |
| |
| Increment the global variable (signals_received) for |
| each received signal. |
| |
| Returns: Nothing |
| |
+---------------------------------------------------------------------*/
void handler (int signal)
{
if (signal == SIGILL) signals_received++;
printf ("\treceived signal: (%s)\n", signames[signal]);
}
/*---------------------------------------------------------------------+
| sys_error () |
| ==================================================================== |
| |
| Function: Creates system error message and calls error () |
| |
+---------------------------------------------------------------------*/
void sys_error (const char *msg, int line)
{
char syserr_msg [256];
sprintf (syserr_msg, "%s: %s\n", msg, strerror (errno));
error (syserr_msg, line);
}
/*---------------------------------------------------------------------+
| error () |
| ==================================================================== |
| |
| Function: Prints out message and exits... |
| |
+---------------------------------------------------------------------*/
void error (const char *msg, int line)
{
fprintf (stderr, "ERROR [line: %d] %s\n", line, msg);
exit (-1);
}