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){
104 for (
int i = 0;
i < NSIG; ++
i) {
127 m_caught[signum] = 1;
130 m_oldActions[signum] != SIG_DFL
132 m_oldActions[signum].sa_handler != SIG_DFL
136 m_oldActions[signum](signum);
138 m_oldActions[signum].sa_handler(signum);
173 #include "GaudiKernel/HashMap.h"
175 #include "GaudiKernel/IIncidentListener.h"
176 #include "GaudiKernel/IIncidentSvc.h"
177 #include "GaudiKernel/IEventProcessor.h"
178 #include "GaudiKernel/AppReturnCode.h"
182 const char *sig_desc(
int signum) {
183 if (signum >= NSIG || signum < 0)
187 case SIGINT:
return "Interrupt";
188 case SIGILL:
return "Illegal instruction";
189 case SIGFPE:
return "Floating point exception";
190 case SIGSEGV:
return "Segmentation fault";
191 case SIGTERM:
return "Terminated";
192 case SIGBREAK:
return "Trace/breakpoint trap";
193 case SIGABRT:
return "Aborted";
197 return sys_siglist[signum];
205 static const SigMap& instance() {
210 inline const std::string &
name(
int signum)
const {
211 return m_num2id[signum];
214 inline const std::string &desc(
int signum)
const {
215 return m_num2desc[signum];
218 inline int signum(
const std::string &str)
const {
219 auto it = m_name2num.find(str);
220 return it != m_name2num.end() ? it->second : -1;
226 #define addSignal(id) i_addSignal(id, #id);
315 inline void i_addSignal(
int signum,
const char *signame) {
316 m_num2id[signum] = signame;
317 m_name2num[signame] = signum;
318 const char* desc = sig_desc(signum);
320 m_num2desc[signum] = desc;
321 m_name2num[desc] = signum;
349 "List of signal names or numbers to use to schedule a stop. "
350 "If the signal is followed by a '+' the signal is propagated the previously "
351 "registered handler (if any).");
358 std::string serviceName(
"Gaudi::Utils::SignalMonitorSvc");
361 error() <<
"Cannot retrieve " << serviceName <<
endmsg;
364 serviceName =
"IncidentSvc";
367 error() <<
"Cannot retrieve " << serviceName <<
endmsg;
373 warning() <<
"Cannot retrieve IProperty interface of ApplicationMgr, "
374 "the return code will not be changed" <<
endmsg;
377 for (std::vector<std::string>::const_iterator signame =
m_usedSignals.begin();
380 if (sigid.first >= 0) {
384 debug() <<
"Stopping on the signals:" <<
endmsg;
385 const SigMap& sigmap(SigMap::instance());
387 debug() <<
"\t" << sigmap.name(
s.first) <<
": "
388 << sigmap.desc(
s.first) <<
" (" <<
s.first <<
")";
389 if (
s.second) debug() <<
" propagated";
395 debug() <<
"Register to the IncidentSvc" <<
endmsg;
404 [&](
const std::pair<int,bool>&
s) {
414 const SigMap& sigmap(SigMap::instance());
417 warning() <<
"Received signal '" << sigmap.name(
s.first)
419 const std::string &desc = sigmap.desc(
s.first);
420 if ( ! desc.empty() ) warning() <<
", " << desc;
421 warning() <<
")" <<
endmsg;
426 error() <<
"Could not set return code of the application ("
435 warning() <<
"Scheduling a stop" <<
endmsg;
436 ep->stopRun().ignore();
439 warning() <<
"Cannot stop the processing because the IEventProcessor interface cannot be retrieved." <<
endmsg;
459 debug() <<
"Decoding signal declaration '" << sig <<
"'" <<
endmsg;
460 if ( sig.empty() || sig ==
"+" ) {
461 debug() <<
"Empty signal, ignored" <<
endmsg;
462 return std::make_pair<int, bool>(-1,
false);
464 const SigMap& sigmap(SigMap::instance());
465 std::string signal = sig;
466 bool propagate =
false;
468 if (signal[signal.size() - 1] ==
'+') {
469 debug() <<
"Must be propagated to previously registered signal handlers" <<
endmsg;
471 signal.erase(signal.size() - 1, 1);
475 if (std::isdigit(signal[0])){
476 std::istringstream ss(signal);
480 signum = sigmap.signum(signal);
483 warning() <<
"Cannot understand signal identifier '" << sig <<
"', ignored" <<
endmsg;
485 verbose() <<
"Matched signal '" << sigmap.name(signum)
487 const std::string &desc = sigmap.desc(signum);
488 if ( ! desc.empty() ) {
489 verbose() <<
", " << desc;
491 verbose() <<
")" <<
endmsg;
493 return std::make_pair(signum, propagate);
const std::string BeginEvent
Processing of a new event has started.
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...
bool m_stopRequested
Flag to remember if the stop has been requested because of a signal.
bool gotSignal(int signum) const
Check if the given signal has been received.
StatusCode finalize() override
SmartIF< IIncidentSvc > m_incidentSvc
Pointer to the incident service.
void clearSignal(int signum)
Clear the flag for the given signal, so that a new occurrence can be identified.
Gaudi::Utils::SignalMonitorSvc g_u_sms
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
auto begin(reverse_wrapper< T > &w)
void i_handle(int signum)
void ignoreSignal(int signum)
Remove the specific signal handler for the requested signal, restoring the previous signal handler...
static void dispatcher(int signum)
Signal handler function.
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.
#define DECLARE_COMPONENT(type)
auto end(reverse_wrapper< T > &w)
virtual void handle(const Incident &)
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.
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.
void setSignal(int signum)
Set the flag for the given signal, as if the signal was received.
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)
Declare a signal to be monitored.
Base class used to extend a class implementing other interfaces.
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.
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.
virtual ~SignalMonitorSvc()
Stop monitoring signals and clear the instance pointer.
Gaudi::Utils::StopSignalHandler g_u_ssh
Helper functions to set/get the application return code.
struct sigaction handler_t