blob: 959c422a58cea22ac1ab929af8a5d38d319df4fd [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_06 |
| ==================================================================== |
| |
| Description: Verifies that when multiple identical signals are sent |
| to a process, at least one is queued. |
| |
| Algorithm: o Block all signals from interrupting the process |
| o Send MAXSIG signals to the current process |
| o Sleep for a short time |
| o Verify that signals are pending |
| o Change the signal mask and suspend execution until |
| a signal interrupts the process |
| o Verify that at least one signal was received |
| |
| System calls: The following system calls are tested: |
| |
| sigprocmask () - Sets the current signal mask |
| sigismember () - Creates and manipulates signal masks |
| sigfillset () - Creates and manipulates signal masks |
| sigpending () - Returns a set of signals that are |
| blocked from delivery |
| sigsuspend () - Automatically changes the set of |
| blocked signals and waits for a signal |
| raise () - Sends a signal to the executing program |
| |
| Usage: signal_test_06 |
| |
| To compile: cc -o signal_test_06 signal_test_06 |
| |
| Last update: Ver. 1.2, 2/7/94 23:24:14 |
| |
| Change Activity |
| |
| Version Date Name Reason |
| 0.1 122193 DJK Wrote initial test for AIX version 4.1 |
| 1.2 020794 DJK Move to "prod" directory |
| |
+---------------------------------------------------------------------*/
#define MAXSIG 1024*1024 /* Number of signals sent to process */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/signal.h>
#include <errno.h>
#ifdef _LINUX_
// bits/signum.h defines _NSIG as 64
#define SIGMAX 64
#endif
/* Function prototypes */
void handler (int, int, struct sigcontext *);
void init_sig ();
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)
{
sigset_t newmask, /* New signal mask */
oldmask, /* Initial signal mask */
pendmask; /* Pending signal mask */
int i; /* Loop index */
/* Print out program header */
printf ("%s: IPC TestSuite program\n\n", *argv);
/* Set up our signal handler */
init_sig ();
/*
* Block ALL signals from interrupting the process
*/
printf ("\tBlock all signals from interrupting the process\n");
if (sigfillset (&newmask) < 0)
error ("sigfillset failed", __LINE__);
if (sigprocmask (SIG_SETMASK, &newmask, &oldmask) < 0)
error ("sigprocmask failed", __LINE__);
/*
* Send MAXSIG signals to the current process -- since ALL of the
* signals are blocked, none of the signals should interrupt the
* process
*/
printf ("\n\tSend MAX (%d) SIGUSR1 signals to the process...\n", MAXSIG);
for (i=0; i<MAXSIG; i++) raise (SIGUSR1);
/*
* Sleep for a short time and the check to ensure that a SIGUSR1
* signal is pending
*/
sleep (2);
printf ("\n\tEnsure at least one SIGUSR1 signal is pending\n");
if (sigpending (&pendmask) < 0)
error ("sigpending failed", __LINE__);
if (sigismember (&pendmask, SIGUSR1) == 0)
error ("sent multiple SIGUSR1 signals to process, " \
"yet none are pending!", __LINE__);
/*
* Change the signal mask to allow signals to interrupt the process
* and then suspend execution until a signal reaches the process
*
* Then verify that at least one signal was received
*/
printf ("\n\tChange signal mask & wait for SIGUSR1 signal\n");
if (sigsuspend(&oldmask) != -1 || errno != 4)
error ("sigsuspend failed", __LINE__);
if (signals_received != 1) {
printf ("Signals are queued! Sent %d signals, " \
"while %d were queued\n",
MAXSIG, signals_received);
}
/* Program completed successfully -- exit */
printf ("\nsuccessful!\n");
return (0);
}
/*---------------------------------------------------------------------+
| handler () |
| ==================================================================== |
| |
| Function: Catches signals and aborts the program if a signal other |
| than SIGUSR1 was received |
| |
| Updates: signals_received - global variable indicating the number |
| of SIGUSR1 signals received |
| |
| Returns: Aborts if an unexpected signal is caught |
| |
+---------------------------------------------------------------------*/
void handler (int signal, int code, struct sigcontext *scp)
{
char msg [256]; /* Buffer for error message */
if (signal != SIGUSR1) {
sprintf (msg, "unexpected signal (%d)", signal);
error (msg, __LINE__);
}
printf ("\tcaught SIGUSR1 (%d) signal\n", signal);
signals_received++;
}
/*---------------------------------------------------------------------+
| init_sig () |
| ==================================================================== |
| |
| 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: n/a |
| |
+---------------------------------------------------------------------*/
void init_sig ()
{
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__);
}
}
}
/*---------------------------------------------------------------------+
| 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);
}