| /* |
| * 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()); |
| } |