You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
219 lines
5.4 KiB
219 lines
5.4 KiB
/*
|
|
* Copyright 2002-2019 Intel Corporation.
|
|
*
|
|
* This software is provided to you as Sample Source Code as defined in the accompanying
|
|
* End User License Agreement for the Intel(R) Software Development Products ("Agreement")
|
|
* section 1.L.
|
|
*
|
|
* This software and the related documents are provided as is, with no express or implied
|
|
* warranties, other than those that are expressly stated in the License.
|
|
*/
|
|
|
|
/*! @file
|
|
* This application tests that a set of synchronous signals (Exceptions) which are raised (sent asynchronously)
|
|
* are received by the handler that was set for them.
|
|
*
|
|
* When 1 is passes as an argument to the application it will also check a different scenarios where some of
|
|
* these signals are blocked when they are raised
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <pthread.h>
|
|
#include <signal.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <signal.h>
|
|
#include <assert.h>
|
|
|
|
volatile int signalsReceived = 0; // Signal bitwise flag
|
|
#define ALL_SYNC_SIGNALS ((1<<SIGFPE)|(1<<SIGSEGV)|(1<<SIGILL)|(1<<SIGBUS)|(1<<SIGTRAP))
|
|
|
|
void Handler(int signum, siginfo_t *siginfo, void *_uctxt);
|
|
|
|
int CheckBlockedAysncExceptions()
|
|
{
|
|
struct sigaction act;
|
|
bzero(&act, sizeof(act));
|
|
act.sa_flags = SA_SIGINFO;
|
|
act.sa_sigaction = Handler;
|
|
|
|
|
|
sigaction(SIGFPE, &act, NULL);
|
|
sigaction(SIGSEGV, &act, NULL);
|
|
sigaction(SIGILL, &act, NULL);
|
|
sigaction(SIGBUS, &act, NULL);
|
|
sigaction(SIGTRAP, &act, NULL);
|
|
|
|
int ret;
|
|
sigset_t sigMask;
|
|
|
|
// Block SIGFPE and SIGSEGV
|
|
sigemptyset(&sigMask);
|
|
sigaddset(&sigMask, SIGFPE);
|
|
sigaddset(&sigMask, SIGSEGV);
|
|
ret = pthread_sigmask(SIG_BLOCK, &sigMask, NULL);
|
|
assert(0 == ret);
|
|
|
|
// Raise some Exceptions (SIGFPE and SIGSEGV among them)
|
|
raise(SIGFPE);
|
|
raise(SIGSEGV);
|
|
raise(SIGILL);
|
|
raise(SIGBUS);
|
|
|
|
// Verify SIGFPE and SIGSEGV were not received in handler
|
|
assert((signalsReceived & (1<<SIGFPE)) == 0);
|
|
assert((signalsReceived & (1<<SIGSEGV)) == 0);
|
|
|
|
// Remove SIGSEGV from the mask and unblock with mask (unblock SIGFPE)
|
|
sigdelset(&sigMask, SIGSEGV);
|
|
ret = pthread_sigmask(SIG_UNBLOCK, &sigMask, NULL);
|
|
assert(0 == ret);
|
|
|
|
// Verify SIGFPE was received in handler
|
|
assert((signalsReceived & (1<<SIGFPE)));
|
|
|
|
// Unblock SIGSEGV
|
|
sigemptyset(&sigMask);
|
|
sigaddset(&sigMask, SIGSEGV);
|
|
ret = pthread_sigmask(SIG_UNBLOCK, &sigMask, NULL);
|
|
assert(0 == ret);
|
|
|
|
// Verify SIGSEGV was received in handler
|
|
assert((signalsReceived & (1<<SIGSEGV)));
|
|
|
|
// Block SIGTRAP (after that raise it)
|
|
sigemptyset(&sigMask);
|
|
sigaddset(&sigMask, SIGTRAP);
|
|
ret = pthread_sigmask(SIG_BLOCK, &sigMask, NULL);
|
|
assert(0 == ret);
|
|
|
|
raise(SIGTRAP);
|
|
|
|
// Verify SIGTRAP wasn't not received in handler
|
|
assert((signalsReceived & (1<<SIGTRAP)) == 0);
|
|
|
|
// Retrieve current mask
|
|
ret = pthread_sigmask(SIG_SETMASK, NULL, &sigMask);
|
|
assert(0 == ret);
|
|
|
|
// Unblock SIGTRAP by removing SIGTRAP from mask and then using SIG_SETMASK.
|
|
// This checks another interesting scenario
|
|
sigdelset(&sigMask, SIGTRAP);
|
|
ret = pthread_sigmask(SIG_SETMASK, &sigMask, NULL);
|
|
assert(0 == ret);
|
|
|
|
// Verify SIGTRAP was received in handler
|
|
assert((signalsReceived & (1<<SIGTRAP)));
|
|
|
|
|
|
// Verify All signals received by handler
|
|
if (signalsReceived == ALL_SYNC_SIGNALS)
|
|
{
|
|
printf("All signals were received in first phase\n");
|
|
}
|
|
else
|
|
{
|
|
printf("Not all signals were received in first phase\n");
|
|
return 1;
|
|
}
|
|
|
|
|
|
//
|
|
// Phase 2, raise a few signals more than once before unblocking (Another case we want to check)
|
|
//
|
|
|
|
// Clear signalsReceived first
|
|
signalsReceived = 0;
|
|
|
|
sigemptyset(&sigMask);
|
|
sigaddset(&sigMask, SIGILL);
|
|
sigaddset(&sigMask, SIGBUS);
|
|
ret = pthread_sigmask(SIG_BLOCK, &sigMask, NULL);
|
|
assert(0 == ret);
|
|
|
|
// SIGILL 3 times, SIGBUS 2 times
|
|
raise(SIGILL);
|
|
raise(SIGSEGV);
|
|
raise(SIGBUS);
|
|
raise(SIGTRAP);
|
|
raise(SIGILL);
|
|
raise(SIGBUS);
|
|
raise(SIGILL);
|
|
|
|
ret = pthread_sigmask(SIG_UNBLOCK, &sigMask, NULL);
|
|
assert(0 == ret);
|
|
|
|
raise(SIGFPE);
|
|
|
|
|
|
// Check again
|
|
if (signalsReceived == ALL_SYNC_SIGNALS)
|
|
{
|
|
printf("All signals were received in second phase\n");
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
printf("Not all signals were received in second phase\n");
|
|
return 1;
|
|
}
|
|
|
|
}
|
|
|
|
int CheckAysncExceptions()
|
|
{
|
|
struct sigaction act;
|
|
bzero(&act, sizeof(act));
|
|
act.sa_flags = SA_SIGINFO;
|
|
act.sa_sigaction = Handler;
|
|
|
|
sigaction(SIGFPE, &act, NULL);
|
|
sigaction(SIGSEGV, &act, NULL);
|
|
sigaction(SIGILL, &act, NULL);
|
|
sigaction(SIGBUS, &act, NULL);
|
|
sigaction(SIGTRAP, &act, NULL);
|
|
|
|
raise(SIGFPE);
|
|
raise(SIGSEGV);
|
|
raise(SIGILL);
|
|
raise(SIGBUS);
|
|
raise(SIGTRAP);
|
|
|
|
if (signalsReceived == ALL_SYNC_SIGNALS)
|
|
{ //Verifying all signals were handled by the handler
|
|
printf("All signals were received\n");
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
printf("Not all signals were received\n");
|
|
return 1;
|
|
}
|
|
|
|
}
|
|
|
|
int main(int argc, char * argv[])
|
|
{
|
|
|
|
if (argc > 1)
|
|
{
|
|
if ( atoi(argv[1]) == 1)
|
|
{
|
|
return CheckBlockedAysncExceptions();
|
|
}
|
|
else
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
return CheckAysncExceptions();
|
|
}
|
|
|
|
|
|
void Handler(int signum, siginfo_t *siginfo, void *_uctxt)
|
|
{
|
|
signalsReceived |=(1<<signum);
|
|
printf("received signal %d\n", signum);
|
|
}
|