8 #define SCARAB_API_EXPORTS 43 LOGGER( slog,
"signal_handler" );
45 bool signal_handler::s_exited =
false;
48 bool signal_handler::s_handling_sig_abrt =
false;
49 bool signal_handler::s_handling_sig_term =
false;
50 bool signal_handler::s_handling_sig_int =
false;
51 bool signal_handler::s_handling_sig_quit =
false;
58 LOGGER( slog_constr,
"signal_handler constructor" );
63 LWARN( slog_constr,
"Unable to setup handling of SIGABRT: abort() and unhandled exceptions will result in an unclean exit" );
67 LDEBUG( slog_constr,
"Handling SIGABRT (abort() and unhandled exceptions)" );
68 s_handling_sig_abrt =
true;
74 LWARN( slog_constr,
"Unable to setup handling of SIGTERM: SIGTERM will result in an unclean exit" );
78 LDEBUG( slog_constr,
"Handling SIGTERM" );
79 s_handling_sig_term =
true;
85 LWARN( slog_constr,
"Unable to setup handling of SIGINT: ctrl-c cancellation will result in an unclean exit" );
89 LDEBUG( slog_constr,
"Handling SIGINT (ctrl-c)" );
90 s_handling_sig_int =
true;
97 LWARN( slog_constr,
"Unable to setup handling of SIGQUIT: ctrl-\\ cancellation will result in an unclean exit" );
101 LDEBUG( slog_constr,
"Handling SIGQUIT (ctrl-\\)" );
102 s_handling_sig_quit =
true;
105 if( signal(SIGPIPE, SIG_IGN) == SIG_ERR )
107 throw error() <<
"Unable to ignore SIGPIPE\n";
135 std::unique_lock< std::recursive_mutex > t_lock(
s_mutex );
142 std::unique_lock< std::recursive_mutex > t_lock(
s_mutex );
149 std::unique_lock< std::recursive_mutex > t_lock(
s_mutex );
156 std::unique_lock< std::recursive_mutex > t_lock(
s_mutex );
157 LDEBUG( slog,
"Resetting signal_handler" );
161 if( s_handling_sig_abrt && signal( SIGABRT, SIG_DFL ) == SIG_ERR )
163 LWARN( slog,
"Unable to switch SIGABRT to default handler" );
167 s_handling_sig_abrt =
false;
170 if( s_handling_sig_term && signal( SIGTERM, SIG_DFL ) == SIG_ERR )
172 LWARN( slog,
"Unable to switch SIGTERM to default handler" );
176 s_handling_sig_term =
false;
179 if( s_handling_sig_int && signal( SIGINT, SIG_DFL ) == SIG_ERR )
181 LWARN( slog,
"Unable to switch SIGINT to default handler" );
185 s_handling_sig_int =
false;
189 if( s_handling_sig_quit && signal( SIGQUIT, SIG_DFL ) == SIG_ERR )
191 LWARN( slog,
"Unable to switch SIGQUIT to default handler" );
195 s_handling_sig_quit =
false;
209 std::unique_lock< std::recursive_mutex > t_lock(
s_mutex );
210 LERROR( slog,
"Handling termination due to an error condition; signal <" << a_sig <<
">" );
217 std::unique_lock< std::recursive_mutex > t_lock(
s_mutex );
218 LPROG( slog,
"Handling termination; signal <" << a_sig <<
">" );
225 std::unique_lock< std::recursive_mutex > t_lock(
s_mutex );
231 std::cerr <<
"Exiting abruptly" << std::endl;
232 std::_Exit( a_code );
237 std::unique_lock< std::recursive_mutex > t_lock(
s_mutex );
239 s_return_code = a_code;
254 if(
auto t_exc_ptr = std::current_exception() )
259 if( a_use_logging ) {
LDEBUG( slog,
"Rethrowing current exception" ); }
260 else { std::cerr <<
"Rethrowing current exception" << std::endl; }
261 std::rethrow_exception( t_exc_ptr );
263 catch(
const std::exception& e ) {
264 if( a_use_logging ) {
LERROR( slog,
"Caught unhandled exception. what(): " << e.what() ); }
265 else { std::cerr <<
"Caught unhandled exception. what(): " << e.what() << std::endl; }
268 if( a_use_logging )
LERROR( slog,
"Caught unknown (non-std::exception) & unhandled exception." )
269 else { std::cerr <<
"Caught unknown (non-std::exception) & unhandled exception." << std::endl; }
278 #ifndef _WIN32 // stack trace printing not implemented for windows 279 void* t_bt_array[50];
280 int t_size = backtrace( t_bt_array, 50 );
282 if( a_use_logging ) {
LERROR( slog,
"Backtrace returned " << t_size <<
" frames\n" ); }
283 else { std::cerr <<
"Backtrace returned " << t_size <<
" frames\n" << std::endl; }
285 char** t_messages = backtrace_symbols( t_bt_array, t_size );
287 std::stringstream t_bt_str;
288 for(
int i = 0; i < t_size && t_messages !=
nullptr; ++i )
290 t_bt_str <<
"[bt]: (" << i <<
") " << t_messages[i] <<
'\n';
292 if( a_use_logging ) {
LERROR( slog,
"Backtrace:\n" << t_bt_str.str() ); }
293 else { std::cerr <<
"Backtrace:\n" << t_bt_str.str() << std::endl; }
302 std::unique_lock< std::recursive_mutex > t_lock(
s_mutex );
303 LDEBUG( slog,
"Canceling all cancelables" );
308 if( ! t_canceler_it->second.expired() )
310 t_canceler_it->second.lock()->cancel( a_code );
313 std::this_thread::sleep_for( std::chrono::seconds(1) );
317 ExitProcess( a_code );
std::weak_ptr< cancelable > cancelable_wptr_t
static void terminate(int a_code) noexcept
Main terminate function – does not cleanup memory or threads.
void add_cancelable(std::shared_ptr< cancelable > a_cancelable)
Add a cancelable object.
static cancelers s_cancelers
std::map< cancelable *, cancelable_wptr_t > cancelers
Deals with cleanly exiting an application, and includes signal and std::terminate handler functions...
LOGGER(mtlog, "authentication")
static std::recursive_mutex s_mutex
Contains the logger class and macros, based on Kasper's KLogger class.
static void print_current_exception(bool a_use_logging)
Prints the current exception, if there is one.
static void cancel_all(int a_code)
Asynchronous call to cancel all cancelables with the given exit code.
static void exit(int a_code)
Main exit function – cleanly exits.
static void handle_exit_error(int a_sig)
Handler for error signals – cleanly exits.
Base class for a cancelable object (i.e. an object that can be canceled by scarab::signal_handler or ...
static void add_cancelable_s(std::shared_ptr< cancelable > a_cancelable)
Static version: add a cancelable object.
void remove_cancelable(std::shared_ptr< cancelable > a_cancelable)
Remove a cancelable object.
void reset()
Remove all cancelables and signal handling.
static void remove_cancelable_s(std::shared_ptr< cancelable > a_cancelable)
Static version: remove a cancelable object.
static void handle_exit_success(int a_sig)
Handler for success signals – cleanly exits.
virtual ~signal_handler()
static void handle_terminate() noexcept
Handler for std::terminate – does not cleanup memory or threads.
static void print_stack_trace(bool a_use_logging)
Prints the stack trace.