Files
compute-runtime/shared/test/common/os_interface/linux/signal_utils.cpp
Artur Harasimiuk 99c5de855c improve error reporting from ULTs
- preserve original stdout and restore in signal handler what is needed
if stdout capture was enabled by GTest framework
- print information about time elapsed on SIGALRM

Signed-off-by: Artur Harasimiuk <artur.harasimiuk@intel.com>
2022-08-18 15:21:53 +02:00

125 lines
3.4 KiB
C++

/*
* Copyright (C) 2022 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "shared/test/common/libult/signal_utils.h"
#include "gtest/gtest.h"
#include <time.h>
#include <unistd.h>
std::string lastTest("");
namespace NEO {
extern const unsigned int ultIterationMaxTime;
}
int newStdOut = -1;
struct sigaction oldSigAbrt;
void handleSIGABRT(int signal) {
if (newStdOut != -1) {
dup2(newStdOut, 1);
}
std::cout << "SIGABRT on: " << lastTest << std::endl;
if (sigaction(SIGABRT, &oldSigAbrt, nullptr) == -1) {
std::cout << "FATAL: cannot fatal SIGABRT handler" << std::endl;
std::cout << "FATAL: try SEGV" << std::endl;
uint8_t *ptr = nullptr;
*ptr = 0;
std::cout << "FATAL: still alive, call exit()" << std::endl;
exit(-1);
}
raise(signal);
}
struct timespec startTimeSpec = {};
struct timespec alrmTimeSpec = {};
void handleSIGALRM(int signal) {
if (newStdOut != -1) {
dup2(newStdOut, 1);
}
std::cout << "Tests timeout: ";
if (clock_gettime(CLOCK_MONOTONIC_RAW, &alrmTimeSpec) == 0) {
auto deltaSec = alrmTimeSpec.tv_sec - startTimeSpec.tv_sec;
std::cout << " after: " << deltaSec << " seconds";
}
std::cout << " on: " << lastTest << std::endl;
abort();
}
void handleSIGSEGV(int signal) {
if (newStdOut != -1) {
dup2(newStdOut, 1);
}
std::cout << "SIGSEGV on: " << lastTest << std::endl;
abort();
}
int setAbrt(bool enableAbrt) {
std::cout << "enable SIGABRT handler: " << enableAbrt << std::endl;
struct sigaction sa;
sa.sa_handler = &handleSIGABRT;
sa.sa_flags = SA_RESTART;
sigfillset(&sa.sa_mask);
if (sigaction(SIGABRT, &sa, &oldSigAbrt) == -1) {
std::cout << "FATAL ERROR: cannot intercept SIGABRT" << std::endl;
return -2;
}
if (newStdOut == -1) {
newStdOut = dup(1);
}
return 0;
}
int setAlarm(bool enableAlarm) {
std::cout << "enable SIGALRM handler: " << enableAlarm << std::endl;
if (enableAlarm) {
if (clock_gettime(CLOCK_MONOTONIC_RAW, &startTimeSpec)) {
startTimeSpec.tv_sec = 0;
}
auto currentUltIterationMaxTime = NEO::ultIterationMaxTime;
auto ultIterationMaxTimeEnv = getenv("NEO_ULT_ITERATION_MAX_TIME");
if (ultIterationMaxTimeEnv != nullptr) {
currentUltIterationMaxTime = atoi(ultIterationMaxTimeEnv);
}
unsigned int alarmTime = currentUltIterationMaxTime * ::testing::GTEST_FLAG(repeat);
struct sigaction sa;
sa.sa_handler = &handleSIGALRM;
sa.sa_flags = SA_RESTART;
sigfillset(&sa.sa_mask);
if (sigaction(SIGALRM, &sa, NULL) == -1) {
std::cout << "FATAL ERROR: cannot intercept SIGALRM" << std::endl;
return -2;
}
if (newStdOut == -1) {
newStdOut = dup(1);
}
alarm(alarmTime);
std::cout << "set timeout to: " << alarmTime << std::endl;
}
return 0;
}
int setSegv(bool enableSegv) {
std::cout << "enable SIGSEGV handler: " << enableSegv << std::endl;
struct sigaction sa;
sa.sa_handler = &handleSIGSEGV;
sa.sa_flags = SA_RESTART;
sigfillset(&sa.sa_mask);
if (sigaction(SIGSEGV, &sa, NULL) == -1) {
std::cout << "FATAL ERROR: cannot intercept SIGSEGV" << std::endl;
return -2;
}
if (newStdOut == -1) {
newStdOut = dup(1);
}
return 0;
}