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";
129 std::unique_lock< std::recursive_mutex > t_lock(
s_mutex );
136 std::unique_lock< std::recursive_mutex > t_lock(
s_mutex );
143 std::unique_lock< std::recursive_mutex > t_lock(
s_mutex );
144 LDEBUG( slog,
"Resetting signal_handler" );
148 if( s_handling_sig_abrt && signal( SIGABRT, SIG_DFL ) == SIG_ERR )
150 LWARN( slog,
"Unable to switch SIGABRT to default handler" );
154 s_handling_sig_abrt =
false;
157 if( s_handling_sig_term && signal( SIGTERM, SIG_DFL ) == SIG_ERR )
159 LWARN( slog,
"Unable to switch SIGTERM to default handler" );
163 s_handling_sig_term =
false;
166 if( s_handling_sig_int && signal( SIGINT, SIG_DFL ) == SIG_ERR )
168 LWARN( slog,
"Unable to switch SIGINT to default handler" );
172 s_handling_sig_int =
false;
176 if( s_handling_sig_quit && signal( SIGQUIT, SIG_DFL ) == SIG_ERR )
178 LWARN( slog,
"Unable to switch SIGQUIT to default handler" );
182 s_handling_sig_quit =
false;
196 std::unique_lock< std::recursive_mutex > t_lock(
s_mutex );
197 LERROR( slog,
"Handling termination due to an error condition; signal <" << a_sig <<
">" );
204 std::unique_lock< std::recursive_mutex > t_lock(
s_mutex );
205 LPROG( slog,
"Handling termination; signal <" << a_sig <<
">" );
212 std::unique_lock< std::recursive_mutex > t_lock(
s_mutex );
218 std::cerr <<
"Exiting abruptly" << std::endl;
219 std::_Exit( a_code );
224 std::unique_lock< std::recursive_mutex > t_lock(
s_mutex );
226 s_return_code = a_code;
241 if(
auto t_exc_ptr = std::current_exception() )
246 if( a_use_logging ) {
LDEBUG( slog,
"Rethrowing current exception" ); }
247 else { std::cerr <<
"Rethrowing current exception" << std::endl; }
248 std::rethrow_exception( t_exc_ptr );
250 catch(
const std::exception& e ) {
251 if( a_use_logging ) {
LERROR( slog,
"Caught unhandled exception. what(): " << e.what() ); }
252 else { std::cerr <<
"Caught unhandled exception. what(): " << e.what() << std::endl; }
255 if( a_use_logging )
LERROR( slog,
"Caught unknown (non-std::exception) & unhandled exception." )
256 else { std::cerr <<
"Caught unknown (non-std::exception) & unhandled exception." << std::endl; }
265 #ifndef _WIN32 // stack trace printing not implemented for windows 266 void* t_bt_array[50];
267 int t_size = backtrace( t_bt_array, 50 );
269 if( a_use_logging ) {
LERROR( slog,
"Backtrace returned " << t_size <<
" frames\n" ); }
270 else { std::cerr <<
"Backtrace returned " << t_size <<
" frames\n" << std::endl; }
272 char** t_messages = backtrace_symbols( t_bt_array, t_size );
274 std::stringstream t_bt_str;
275 for(
int i = 0; i < t_size && t_messages !=
nullptr; ++i )
277 t_bt_str <<
"[bt]: (" << i <<
") " << t_messages[i] <<
'\n';
279 if( a_use_logging ) {
LERROR( slog,
"Backtrace:\n" << t_bt_str.str() ); }
280 else { std::cerr <<
"Backtrace:\n" << t_bt_str.str() << std::endl; }
289 std::unique_lock< std::recursive_mutex > t_lock(
s_mutex );
290 LDEBUG( slog,
"Canceling all cancelables" );
296 std::this_thread::sleep_for( std::chrono::seconds(1) );
300 ExitProcess( a_code );
static void terminate(int a_code) noexcept
Main terminate function – does not cleanup memory or threads.
static cancelers s_cancelers
Deals with cleanly exiting an application, and includes signal and std::terminate handler functions...
LOGGER(mtlog, "authentication")
static std::recursive_mutex s_mutex
static void remove_cancelable_s(cancelable *a_cancelable)
Static version: remove a cancelable object.
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 add_cancelable_s(cancelable *a_cancelable)
Static version: add a cancelable object.
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.
void add_cancelable(cancelable *a_cancelable)
Add a cancelable object.
void remove_cancelable(cancelable *a_cancelable)
Remove a cancelable object.
void reset()
Remove all cancelables and signal handling.
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.
std::set< cancelable *> cancelers