7 #include "GaudiKernel/Service.h"
8 #include "GaudiUtils/ISignalMonitor.h"
31 typedef struct sigaction handler_t;
42 oldact = signal(signum, sa);
45 sigemptyset(&sa.sa_mask);
47 sigaction(signum, &sa, &oldact);
93 for(
int i = 0;
i < NSIG; ++
i){
125 m_caught[signum] = 1;
128 m_oldActions[signum] != SIG_DFL
130 m_oldActions[signum].sa_handler != SIG_DFL
134 m_oldActions[signum](signum);
136 m_oldActions[signum].sa_handler(signum);
171 #include "GaudiKernel/HashMap.h"
173 #include "GaudiKernel/IIncidentListener.h"
174 #include "GaudiKernel/IIncidentSvc.h"
175 #include "GaudiKernel/IEventProcessor.h"
176 #include "GaudiKernel/AppReturnCode.h"
180 const char *sig_desc(
int signum) {
181 if (signum >= NSIG || signum < 0)
185 case SIGINT:
return "Interrupt";
186 case SIGILL:
return "Illegal instruction";
187 case SIGFPE:
return "Floating point exception";
188 case SIGSEGV:
return "Segmentation fault";
189 case SIGTERM:
return "Terminated";
190 case SIGBREAK:
return "Trace/breakpoint trap";
191 case SIGABRT:
return "Aborted";
195 return sys_siglist[signum];
203 static const SigMap& instance() {
208 inline const std::string &
name(
int signum)
const {
209 return m_num2id[signum];
212 inline const std::string &desc(
int signum)
const {
213 return m_num2desc[signum];
216 inline int signum(
const std::string &str)
const {
217 auto it = m_name2num.find(str);
218 return it != m_name2num.end() ? it->second : -1;
224 #define addSignal(id) i_addSignal(id, #id);
313 inline void i_addSignal(
int signum,
const char *signame) {
314 m_num2id[signum] = signame;
315 m_name2num[signame] = signum;
316 const char* desc = sig_desc(signum);
318 m_num2desc[signum] = desc;
319 m_name2num[desc] = signum;
347 "List of signal names or numbers to use to schedule a stop. "
348 "If the signal is followed by a '+' the signal is propagated the previously "
349 "registered handler (if any).");
356 std::string serviceName(
"Gaudi::Utils::SignalMonitorSvc");
359 error() <<
"Cannot retrieve " << serviceName <<
endmsg;
362 serviceName =
"IncidentSvc";
365 error() <<
"Cannot retrieve " << serviceName <<
endmsg;
371 warning() <<
"Cannot retrieve IProperty interface of ApplicationMgr, "
372 "the return code will not be changed" <<
endmsg;
377 if (sigid.first >= 0) {
381 debug() <<
"Stopping on the signals:" <<
endmsg;
382 const SigMap& sigmap(SigMap::instance());
384 debug() <<
"\t" << sigmap.name(
s.first) <<
": "
385 << sigmap.desc(
s.first) <<
" (" <<
s.first <<
")";
386 if (
s.second) debug() <<
" propagated";
392 debug() <<
"Register to the IncidentSvc" <<
endmsg;
401 [&](
const std::pair<int,bool>&
s) {
411 const SigMap& sigmap(SigMap::instance());
414 warning() <<
"Received signal '" << sigmap.name(
s.first)
416 const std::string &desc = sigmap.desc(
s.first);
417 if ( ! desc.empty() ) warning() <<
", " << desc;
418 warning() <<
")" <<
endmsg;
423 error() <<
"Could not set return code of the application ("
432 warning() <<
"Scheduling a stop" <<
endmsg;
433 ep->stopRun().ignore();
436 warning() <<
"Cannot stop the processing because the IEventProcessor interface cannot be retrieved." <<
endmsg;
456 debug() <<
"Decoding signal declaration '" << sig <<
"'" <<
endmsg;
457 if ( sig.empty() || sig ==
"+" ) {
458 debug() <<
"Empty signal, ignored" <<
endmsg;
461 const SigMap& sigmap(SigMap::instance());
462 std::string signal = sig;
463 bool propagate =
false;
465 if (signal[signal.size() - 1] ==
'+') {
466 debug() <<
"Must be propagated to previously registered signal handlers" <<
endmsg;
468 signal.erase(signal.size() - 1, 1);
472 if (std::isdigit(signal[0])){
473 std::istringstream ss(signal);
477 signum = sigmap.signum(signal);
480 warning() <<
"Cannot understand signal identifier '" << sig <<
"', ignored" <<
endmsg;
482 verbose() <<
"Matched signal '" << sigmap.name(signum)
484 const std::string &desc = sigmap.desc(signum);
485 if ( ! desc.empty() ) {
486 verbose() <<
", " << desc;
488 verbose() <<
")" <<
endmsg;
490 return {signum, propagate};
void setSignal(int signum) override
Set the flag for the given signal, as if the signal was received.
StatusCode initialize() override
sig_atomic_t m_caught[NSIG]
Array of flags for received signals.
Small smart pointer class with automatic reference counting for IInterface.
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
bool m_stopRequested
Flag to remember if the stop has been requested because of a signal.
StatusCode finalize() override
SmartIF< IIncidentSvc > m_incidentSvc
Pointer to the incident service.
Gaudi::Utils::SignalMonitorSvc g_u_sms
~SignalMonitorSvc() override
Stop monitoring signals and clear the instance pointer.
auto begin(reverse_wrapper< T > &w)
void i_handle(int signum)
void ignoreSignal(int signum) override
Remove the specific signal handler for the requested signal, restoring the previous signal handler...
static void dispatcher(int signum)
Signal handler function.
void clearSignal(int signum) override
Clear the flag for the given signal, so that a new occurrence can be identified.
StatusCode finalize() override
SmartIF< Gaudi::ISignalMonitor > m_signalMonitor
Pointer to the signal monitor service.
std::vector< std::string > m_usedSignals
List of signal names or numbers (encoded as strings) to use to schedule a stop.
bool isFailure() const
Test for a status code of FAILURE.
MonitoringMode
Possible monitoring modes.
std::map< int, bool > m_signals
Map of monitored signal numbers to the flag telling if they have to be propagated or not...
static void setInstance(SignalMonitorSvc *i)
static SignalMonitorSvc * instance()
Method to get the singleton instance.
Implementation of Gaudi::ISignalMonitor.
auto end(reverse_wrapper< T > &w)
This class is used for returning status codes from appropriate routines.
SignalMonitorSvc(const std::string &name, ISvcLocator *svcLoc)
Initialize internal variables of the service and set the instance pointer.
#define DECLARE_COMPONENT(type)
void handle(const Incident &) override
SmartIF< IProperty > m_appProperty
Pointer to the interface to set the return code of the application.
std::pair< int, bool > i_decodeSignal(const std::string &sig)
Function to translate the signal name to the signal number.
Service that stop the processing if a signal is received.
StatusCode setAppReturnCode(SmartIF< IProperty > &appmgr, int value, bool force=false)
Set the application return code.
static SignalMonitorSvc * s_instance
Pointer to the current instance.
void monitorSignal(int signum, bool propagate) override
Declare a signal to be monitored.
Base class used to extend a class implementing other interfaces.
bool gotSignal(int signum) const override
Check if the given signal has been received.
Base class for all Incidents (computing events).
virtual void addListener(IIncidentListener *lis, const std::string &type="", long priority=0, bool rethrow=false, bool singleShot=false)=0
Add listener.
StatusCode initialize() override
The IEventProcessor is the interface to process events.
StopSignalHandler(const std::string &name, ISvcLocator *svcLoc)
MonitoringMode m_monitored[NSIG]
Array of flags to keep track of monitored signals.
constexpr int SignalOffset
void reset(TYPE *ptr=nullptr)
Set the internal pointer to the passed one disposing of the old one.
handler_t m_oldActions[NSIG]
List of replaced signal actions (for the recovery when disable the monitoring).
virtual void removeListener(IIncidentListener *lis, const std::string &type="")=0
Remove listener.
handler_t m_defaultAction
Helper variable for default signal action.
Gaudi::Utils::StopSignalHandler g_u_ssh
Helper functions to set/get the application return code.
struct sigaction handler_t