From 9afe9932bc8814e3027242740ac2f69f31032e09 Mon Sep 17 00:00:00 2001 From: Jason Lowe-Power Date: Thu, 30 Nov 2023 07:27:52 -0800 Subject: [PATCH] sim,python: Restore sigint handler in python (#531) Currently, if you try to use ctrl-c while python code is running nothing happens. This is not ideal. This change enables users to use ctrl-c while python is running (e.g., when a large disk image is downloading). To do this, we moved the `initSignals` function in gem5 from `main` to the simulate loop. Thus, every time the simulate loop starts (i.e., is called from python) gem5 will install its signal handlers. Also, when the control is returned to python, we put python's default SIGINT handler back. Change-Id: I14490e48d931eb316e8c641217bf8d8ddaa340ed Signed-off-by: Jason Lowe-Power --- src/sim/init_signals.cc | 23 ++++++++++++++++++----- src/sim/init_signals.hh | 4 ++++ src/sim/simulate.cc | 8 ++++++++ 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/sim/init_signals.cc b/src/sim/init_signals.cc index b9aa6f6e4d..b574f12ea1 100644 --- a/src/sim/init_signals.cc +++ b/src/sim/init_signals.cc @@ -84,7 +84,8 @@ setupAltStack() static void installSignalHandler(int signal, void (*handler)(int sigtype), - int flags = SA_RESTART) + int flags = SA_RESTART, + struct sigaction *old_sa = NULL) { struct sigaction sa; @@ -93,7 +94,7 @@ installSignalHandler(int signal, void (*handler)(int sigtype), sa.sa_handler = handler; sa.sa_flags = flags; - if (sigaction(signal, &sa, NULL) == -1) + if (sigaction(signal, &sa, old_sa) == -1) panic("Failed to setup handler for signal %i\n", signal); } @@ -196,9 +197,6 @@ initSignals() // Dump intermediate stats and reset them installSignalHandler(SIGUSR2, dumprstStatsHandler); - // Exit cleanly on Interrupt (Ctrl-C) - installSignalHandler(SIGINT, exitNowHandler); - // Print the current cycle number and a backtrace on abort. Make // sure the signal is unmasked and the handler reset when a signal // is delivered to be able to invoke the default handler. @@ -218,4 +216,19 @@ initSignals() installSignalHandler(SIGIO, ioHandler); } +struct sigaction old_int_sa; + +void initSigInt() +{ + // Exit cleanly on Interrupt (Ctrl-C) + installSignalHandler(SIGINT, exitNowHandler, SA_RESTART, &old_int_sa); +} + +void restoreSigInt() +{ + // Restore the old SIGINT handler + sigaction(SIGINT, &old_int_sa, NULL); +} + + } // namespace gem5 diff --git a/src/sim/init_signals.hh b/src/sim/init_signals.hh index ea9f3d5229..2da3aae877 100644 --- a/src/sim/init_signals.hh +++ b/src/sim/init_signals.hh @@ -38,6 +38,10 @@ void exitNowHandler(int sigtype); void abortHandler(int sigtype); void initSignals(); +// separate out sigint handler so that we can restore the python one +void initSigInt(); +void restoreSigInt(); + } // namespace gem5 #endif // __SIM_INIT_SIGNALS_HH__ diff --git a/src/sim/simulate.cc b/src/sim/simulate.cc index abd2b1d391..6505f57904 100644 --- a/src/sim/simulate.cc +++ b/src/sim/simulate.cc @@ -50,6 +50,7 @@ #include "base/types.hh" #include "sim/async.hh" #include "sim/eventq.hh" +#include "sim/init_signals.hh" #include "sim/sim_events.hh" #include "sim/sim_exit.hh" #include "sim/stat_control.hh" @@ -187,6 +188,10 @@ GlobalSimLoopExitEvent *global_exit_event= nullptr; GlobalSimLoopExitEvent * simulate(Tick num_cycles) { + // install the sigint handler to catch ctrl-c and exit the sim loop cleanly + // Note: This should be done before initializing the threads + initSigInt(); + if (global_exit_event)//cleaning last global exit event global_exit_event->clean(); std::unique_ptr quantum_event; @@ -229,6 +234,9 @@ simulate(Tick num_cycles) Event *local_event = doSimLoop(mainEventQueue[0]); assert(local_event); + // Restore normal ctrl-c operation as soon as the event queue is done + restoreSigInt(); + inParallelMode = false; // locate the global exit event and return it to Python