Files
revng-revng/lib/Support/OnQuit.cpp
T
Giacomo Vercesi dc90bca33e revng/Support: split part of Statistics in OnQuit
Split the OnQuit functionality of Statistics as a separate header and
object file. Rework the interface to use lambdas instead of the
OnQuitInterface.
2023-09-06 15:23:43 +02:00

65 lines
1.7 KiB
C++

/// \file OnQuit.cpp
/// \brief Implementation of the OnQuit registry that allows running operation
/// at shutdown.
//
// This file is distributed under the MIT License. See LICENSE.md for details.
//
#include <array>
#include <csignal>
#include "revng/Support/Assert.h"
#include "revng/Support/Debug.h"
#include "revng/Support/OnQuit.h"
struct Handler {
int Signal;
bool Restore;
struct sigaction OldHandler;
struct sigaction NewHandler;
};
// Print statistics on SIGINT (Ctrl + C), SIGABRT (assertions) and SIGUSR1.
// For SIGUSR1, don't terminate program execution.
static std::array<Handler, 4> Handlers = { { { SIGINT, true, {}, {} },
{ SIGTERM, true, {}, {} },
{ SIGABRT, true, {}, {} },
{ SIGUSR1, false, {}, {} } } };
llvm::ManagedStatic<OnQuitRegistry> OnQuit;
static void onQuitSignalHandler(int Signal) {
Handler *SignalHandler = nullptr;
for (Handler &H : Handlers)
if (H.Signal == Signal)
SignalHandler = &H;
// Assert we were notified of the signal we expected
revng_assert(SignalHandler != nullptr);
OnQuit->quit();
if (not SignalHandler->Restore)
return;
int Result = sigaction(Signal, &SignalHandler->OldHandler, nullptr);
revng_assert(Result == 0);
raise(Signal);
}
void OnQuitRegistry::install() {
// Register signal handlers
for (Handler &H : Handlers) {
H.NewHandler.sa_handler = &onQuitSignalHandler;
int Result = sigaction(H.Signal, &H.NewHandler, &H.OldHandler);
revng_assert(Result == 0);
}
}
void OnQuitRegistry::quit() {
for (std::function<void()> &Handler : Registry)
Handler();
}