blob: edcad9e933518cdee3f5d766e9feeaf326af097b [file] [log] [blame]
/*
* This file defines a signal handler used by VPR to catch SIGINT signals
* (ctrl-C from terminal) on POSIX systems. It is only active if
* VPR_USE_SIGACTION is defined.
*
* If a SIGINT occur the handler sets the 'forced_pause' flag of the VPR
* context. If 'forced_pause' is still true when another SIGINT occurs an
* exception is thrown (typically ending the program).
*/
#include "vtr_log.h"
#include "vtr_time.h"
#include "vpr_signal_handler.h"
#include "vpr_exit_codes.h"
#include "vpr_error.h"
#include "globals.h"
#include "read_place.h"
#include "route_export.h"
#include <atomic>
#ifdef VPR_USE_SIGACTION
# include <csignal>
#endif
void vpr_signal_handler(int signal);
void checkpoint();
std::atomic<int> uncleared_sigint_count(0);
#ifdef VPR_USE_SIGACTION
void vpr_install_signal_handler() {
//Install the signal handler for SIGINT (i.e. ctrl+C from the terminal)
struct sigaction sa;
sa.sa_handler = vpr_signal_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0; //Make sure the flags are cleared
sigaction(SIGINT, &sa, nullptr); //Keyboard interrupt (1 pauses, 2 quits)
sigaction(SIGHUP, &sa, nullptr); //Hangup (attempts to checkpoint)
sigaction(SIGTERM, &sa, nullptr); //Terminate (attempts to checkpoint, then exit)
}
void vpr_signal_handler(int signal) {
if (signal == SIGINT) {
if (g_vpr_ctx.forced_pause()) {
uncleared_sigint_count++; //Previous SIGINT uncleared
} else {
uncleared_sigint_count.store(1); //Only this SIGINT outstanding
}
if (uncleared_sigint_count == 1) {
VTR_LOG("Recieved SIGINT: try again to really exit...\n");
} else if (uncleared_sigint_count == 2) {
VTR_LOG("Recieved two uncleared SIGINTs: Attempting to checkpoint and exit...\n");
checkpoint();
std::quick_exit(INTERRUPTED_EXIT_CODE);
} else if (uncleared_sigint_count == 3) {
//Really exit (e.g. SIGINT while checkpointing)
VTR_LOG("Recieved three uncleared SIGINTs: Exiting...\n");
std::quick_exit(INTERRUPTED_EXIT_CODE);
}
} else if (signal == SIGHUP) {
VTR_LOG("Recieved SIGHUP: Attempting to checkpoint...\n");
checkpoint();
} else if (signal == SIGTERM) {
VTR_LOG("Recieved SIGTERM: Attempting to checkpoint then exit...\n");
checkpoint();
std::quick_exit(INTERRUPTED_EXIT_CODE);
}
}
#else
//No signal support all operations are no-ops
void vpr_install_signal_handler() {
//Do nothing
}
void vpr_signal_handler(int /*signal*/) {
//Do nothing
}
#endif
void checkpoint() {
//Dump the current placement and routing state
vtr::ScopedStartFinishTimer timer("Checkpointing");
std::string placer_checkpoint_file = "placer_checkpoint.place";
VTR_LOG("Attempting to checkpoint current placement to file: %s\n", placer_checkpoint_file.c_str());
print_place(nullptr, nullptr, placer_checkpoint_file.c_str());
std::string router_checkpoint_file = "router_checkpoint.route";
VTR_LOG("Attempting to checkpoint current routing to file: %s\n", router_checkpoint_file.c_str());
print_route(nullptr, router_checkpoint_file.c_str());
}