From 03d6105c6cf06186cd761f04932ba8d5e9e9c270 Mon Sep 17 00:00:00 2001 From: Alex Lin Date: Fri, 15 Apr 2016 14:57:22 -0500 Subject: [PATCH] Remove catches for non-Trick exceptions Removed the catches for std:exceptions and unknown exceptions. The best way I found to provide a clue to where the exception comes from is to allow the handler for unhandled exceptions execute. This is std::terminate which calls abort and trips a SIGABRT. I added a signal handler for SIGABRT which like SIGSEGV, we can print a stack trace or attach a debugger to the process before exiting. The stack trace print is on by default. By default the signal handler is on, stack trace is on, debugger is off. refs #220 --- include/trick/Executive.hh | 23 +++++++++++ .../sim_services/Executive/Executive.cpp | 5 +++ .../Executive/Executive_c_intf.cpp | 24 +++++++++++ .../sim_services/Executive/Executive_init.cpp | 19 --------- .../Executive_init_signal_handlers.cpp | 28 ++++++++++++- .../sim_services/Executive/Executive_loop.cpp | 21 +--------- .../Executive_set_thread_rt_semaphore.cpp | 2 + .../Executive/Executive_shutdown.cpp | 13 ------ .../Executive/Executive_signal_handler.cpp | 5 ++- .../sim_services/Executive/Threads_child.cpp | 40 ------------------- 10 files changed, 86 insertions(+), 94 deletions(-) diff --git a/include/trick/Executive.hh b/include/trick/Executive.hh index 4d370705..3e08450d 100644 --- a/include/trick/Executive.hh +++ b/include/trick/Executive.hh @@ -65,6 +65,9 @@ namespace Trick { /** Allows the trapping of SIGSEGV signals and graceful shutdown.\n */ bool trap_sigsegv; /**< trick_units(--) */ + /** Allows the trapping of SIGABRT signals and graceful shutdown.\n */ + bool trap_sigabrt; /**< trick_units(--) */ + /** Flags a restart was loaded\n */ bool restart_called; /**< trick_io(**) trick_units(--) */ @@ -512,6 +515,14 @@ namespace Trick { */ bool get_trap_sigsegv() ; + /** + @userdesc Command to get the trap sigsegv toggle value (will SIGSEGV signal be trapped). + @par Python Usage: + @code = trick.exec_get_trap_sigsegv() @endcode + @return boolean (C integer 0/1) Executive::trap_sigsegv + */ + bool get_trap_sigabrt() ; + /** @brief @userdesc Command to set the attach debugger toggle value. @param on_off - boolean yes (C integer 1) = attach debugger if signal shuts sim down. no (C integer 0) = do not attach debugger. @@ -674,6 +685,18 @@ namespace Trick { */ int set_trap_sigsegv(bool on_off) ; + /** + @userdesc Command to enable/disable the trapping of SIGABRT signals and a graceful shutdown. + Setting on_off to true (default) will trap the operating system communications bus error signal and then + perforam a graceful simulation shutdown. If on_off is false, the signal will not be trapped and + termination will occur producing a core file. + @par Python Usage: + @code trick.exec_set_trap_sigabrt() @endcode + @param on_off - boolean yes (C integer 1) = enable trap, no (C integer 0) = disable trap + @return always 0 + */ + int set_trap_sigabrt(bool on_off) ; + /** @userdesc Command to get the simulation time in seconds. Formula for simulation time is time_tics / time_tic_value. diff --git a/trick_source/sim_services/Executive/Executive.cpp b/trick_source/sim_services/Executive/Executive.cpp index d46d9dae..b08978d9 100644 --- a/trick_source/sim_services/Executive/Executive.cpp +++ b/trick_source/sim_services/Executive/Executive.cpp @@ -57,6 +57,7 @@ Trick::Executive::Executive() { trap_sigbus = false ; trap_sigfpe = false ; trap_sigsegv = false ; + trap_sigabrt = false ; build_date = std::string("unknown") ; current_version = std::string("unknown") ; @@ -257,6 +258,10 @@ bool Trick::Executive::get_trap_sigsegv() { return(trap_sigsegv) ; } +bool Trick::Executive::get_trap_sigabrt() { + return(trap_sigabrt) ; +} + void Trick::Executive::reset_job_cycle_times() { unsigned int ii ; for ( ii = 0 ; ii < all_jobs_vector.size() ; ii++ ) { diff --git a/trick_source/sim_services/Executive/Executive_c_intf.cpp b/trick_source/sim_services/Executive/Executive_c_intf.cpp index fa5dd551..43e03c80 100644 --- a/trick_source/sim_services/Executive/Executive_c_intf.cpp +++ b/trick_source/sim_services/Executive/Executive_c_intf.cpp @@ -378,6 +378,18 @@ extern "C" int exec_get_trap_sigsegv() { return -1 ; } +/** + * @relates Trick::Executive + * @copydoc Trick::Executive::get_trap_sigabrt + * C wrapper for Trick::Executive::get_trap_sigabrt + */ +extern "C" int exec_get_trap_sigabrt() { + if ( the_exec != NULL ) { + return (int)the_exec->get_trap_sigabrt() ; + } + return -1 ; +} + // -------------------------- SET ------------------------ /** @@ -593,6 +605,18 @@ extern "C" int exec_set_trap_sigsegv( int on_off ) { return -1 ; } +/** + * @relates Trick::Executive + * @copydoc Trick::Executive::set_trap_sigsegv + * C wrapper for Trick::Executive::set_trap_sigsegv + */ +extern "C" int exec_set_trap_sigabrt( int on_off ) { + if ( the_exec != NULL ) { + return the_exec->set_trap_sigabrt((bool)on_off) ; + } + return -1 ; +} + /** * @relates Trick::Executive * @copydoc Trick::Executive::set_job_onoff diff --git a/trick_source/sim_services/Executive/Executive_init.cpp b/trick_source/sim_services/Executive/Executive_init.cpp index 6b959c6c..935878ed 100644 --- a/trick_source/sim_services/Executive/Executive_init.cpp +++ b/trick_source/sim_services/Executive/Executive_init.cpp @@ -62,25 +62,6 @@ int Trick::Executive::init() { except_file = ex.file ; except_message = ex.message ; return(-1) ; - } catch (const std::exception &ex) { - if ( curr_job != NULL ) { - except_file = curr_job->name ; - } else { - except_file = "somewhere in Executive::init" ; - } - fprintf(stderr, "\nExecutive::init terminated with std::exception\n ROUTINE: %s\n DIAGNOSTIC: %s\n", - except_file.c_str(), ex.what()) ; - exit(-1) ; - } catch (...) { - if ( curr_job != NULL ) { - except_file = curr_job->name ; - } else { - except_file = "somewhere in Executive::init" ; - } - except_message = "unknown error" ; - fprintf(stderr, "\nExecutive::init terminated with unknown exception\n ROUTINE: %s\n DIAGNOSTIC: %s\n", - except_file.c_str() , except_message.c_str()) ; - exit(-1) ; } /* return 0 if there are no errors. */ diff --git a/trick_source/sim_services/Executive/Executive_init_signal_handlers.cpp b/trick_source/sim_services/Executive/Executive_init_signal_handlers.cpp index 29a771da..def041df 100644 --- a/trick_source/sim_services/Executive/Executive_init_signal_handlers.cpp +++ b/trick_source/sim_services/Executive/Executive_init_signal_handlers.cpp @@ -112,7 +112,32 @@ int Trick::Executive::set_trap_sigsegv(bool on_off) { /** @details --# Catch SIGBUS and SIGSEGV errors. Don't catch SIGFPE +-# If incoming on_off flag is true assign sig_hand() as the signal handler for SIGSEGV +-# Else revert to the default signal handler SIG_DFL. +-# set trap_sigabrt to the current on_off status + Requirement [@ref r_exec_signal_0]. +*/ +int Trick::Executive::set_trap_sigabrt(bool on_off) { + static struct sigaction sigact; + + if ( on_off ) { + /* Assign sig_hand() as the signal handler for SIGABRT */ + sigact.sa_handler = (void (*)(int)) sig_hand; + } else { + sigact.sa_handler = SIG_DFL; + } + + if (sigaction(SIGABRT, &sigact, NULL) < 0) { + perror("sigaction() failed for SIGSEGV"); + } else { + trap_sigabrt = on_off ; + } + return(0) ; +} + +/** +@details +-# Catch SIGBUS, SIGSEGV, and SIGABRT errors. Don't catch SIGFPE -# Assign ctrl_c_hand() as the signal handler for SIGINT. Requirement [@ref r_exec_signal_0]. -# Assign sig_hand() as the signal handler for SIGTERM. @@ -128,6 +153,7 @@ int Trick::Executive::init_signal_handlers() { set_trap_sigbus(true) ; set_trap_sigfpe(false) ; set_trap_sigsegv(true) ; + set_trap_sigabrt(true) ; /* Assign ctrl_c_hand() as the default signal handler for SIGINT ( keypress). */ sigact.sa_handler = (void (*)(int)) ctrl_c_hand; diff --git a/trick_source/sim_services/Executive/Executive_loop.cpp b/trick_source/sim_services/Executive/Executive_loop.cpp index b400ce80..9879d13d 100644 --- a/trick_source/sim_services/Executive/Executive_loop.cpp +++ b/trick_source/sim_services/Executive/Executive_loop.cpp @@ -1,6 +1,7 @@ #include +#include #include "trick/Executive.hh" #include "trick/ExecutiveException.hh" @@ -52,26 +53,6 @@ int Trick::Executive::loop() { except_file = ex.file ; except_message = ex.message ; return(ex.ret_code) ; - } catch (const std::exception &ex) { - if ( curr_job != NULL ) { - except_file = curr_job->name ; - } else { - except_file = "somewhere in Executive::run" ; - } - fprintf(stderr, "\nExecutive::loop terminated with std::exception\n ROUTINE: %s\n DIAGNOSTIC: %s\n" - " STOP TIME: %f\n" , except_file.c_str() , ex.what() , get_sim_time()) ; - exit(-1) ; - } catch (...) { - /* Handle unknown exceptions. Set the file name and error message to unknown. exit -1. */ - if ( curr_job != NULL ) { - except_file = curr_job->name ; - } else { - except_file = "somewhere in Executive::run" ; - } - except_message = "unknown error" ; - fprintf(stderr, "\nExecutive::loop terminated with unknown exception\n ROUTINE: %s\n DIAGNOSTIC: %s\n" - " STOP TIME: %f\n" , except_file.c_str() , except_message.c_str() , get_sim_time()) ; - exit(-1) ; } /* return 0 if there are no errors. */ diff --git a/trick_source/sim_services/Executive/Executive_set_thread_rt_semaphore.cpp b/trick_source/sim_services/Executive/Executive_set_thread_rt_semaphore.cpp index a0fb7bac..bbc03fda 100644 --- a/trick_source/sim_services/Executive/Executive_set_thread_rt_semaphore.cpp +++ b/trick_source/sim_services/Executive/Executive_set_thread_rt_semaphore.cpp @@ -3,6 +3,8 @@ #include "trick/message_proto.h" int Trick::Executive::set_thread_rt_semaphores(unsigned int thread_id , bool yes_no) { + (void)thread_id ; + (void)yes_no ; message_publish(MSG_WARNING, "set_thread_rt_semaphores has been deprecated\n" "Use exec_get_thread(thread_id).set_trigger_type(Trick::ThreadTriggerType tt_type)") ; return -1 ; diff --git a/trick_source/sim_services/Executive/Executive_shutdown.cpp b/trick_source/sim_services/Executive/Executive_shutdown.cpp index 5ec9ba00..3c84d7b4 100644 --- a/trick_source/sim_services/Executive/Executive_shutdown.cpp +++ b/trick_source/sim_services/Executive/Executive_shutdown.cpp @@ -73,19 +73,6 @@ int Trick::Executive::shutdown() { except_return = ex.ret_code ; except_file += std::string(" then exception caught in ") + ex.file ; except_message += std::string(" then exception Message: ") + ex.message ; - } catch (const std::exception &ex) { - except_return = -1 ; - if ( curr_job != NULL ) { - except_file += " " + curr_job->name ; - } else { - except_file += " somewhere in Executive::shutdown" ; - } - except_message += std::string("standard exception caught") + ex.what(); - } catch (...) { - /* Handle unknown exceptions. Set the file name and error message to unknown. Return -1. */ - except_return = -1 ; - except_file = "somewhere in shutdown()" ; - except_message = "unknown error" ; } getrusage(RUSAGE_SELF, &cpu_usage_buf); diff --git a/trick_source/sim_services/Executive/Executive_signal_handler.cpp b/trick_source/sim_services/Executive/Executive_signal_handler.cpp index 89c33baf..77e221b2 100644 --- a/trick_source/sim_services/Executive/Executive_signal_handler.cpp +++ b/trick_source/sim_services/Executive/Executive_signal_handler.cpp @@ -45,6 +45,9 @@ void Trick::Executive::signal_handler(int sig) { case SIGSEGV: /* Segmentation fault */ write( 2 , "SIGSEGV" , 7 ) ; break; + case SIGABRT: /* Abort */ + write( 2 , "SIGABRT" , 7 ) ; + break; default: /* Unrecognized signal */ write( 2 , "unknown" , 7 ) ; break; @@ -61,7 +64,7 @@ void Trick::Executive::signal_handler(int sig) { sprintf(command, "%s -silent /proc/%d/exe %d", debugger_command.c_str(), getpid(), getpid()); system(command); } else if (stack_trace == true ) { - sprintf(command, "%s -silent -batch -x ${TRICK_HOME}/bin/gdb_commands " + sprintf(command, "%s -silent -batch -x ${TRICK_HOME}/share/trick/gdb_commands " "/proc/%d/exe %d | grep -A 20 \"signal handler\"", debugger_command.c_str(), getpid(), getpid()); system(command); } diff --git a/trick_source/sim_services/Executive/Threads_child.cpp b/trick_source/sim_services/Executive/Threads_child.cpp index 792d9662..0291af8f 100644 --- a/trick_source/sim_services/Executive/Threads_child.cpp +++ b/trick_source/sim_services/Executive/Threads_child.cpp @@ -218,51 +218,11 @@ void * Trick::Threads::thread_body() { " THREAD STOP TIME: %f\n" , thread_id, ex.file.c_str(), ex.message.c_str(), exec_get_sim_time()) ; exit(ex.ret_code) ; - } catch (const std::exception &ex) { - std::string except_file ; - if ( curr_job != NULL ) { - except_file = curr_job->name ; - } else { - except_file = "somewhere in Executive::run" ; - } - fprintf(stderr, "\nCHILD THREAD %d TERMINATED with exec_terminate\n ROUTINE: %s\n DIAGNOSTIC: %s\n" - " THREAD STOP TIME: %f\n" , - thread_id, except_file.c_str() , ex.what(), exec_get_sim_time()) ; - exit(-1) ; #ifdef __linux -#ifdef __GNUC__ -#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 2 // for post gcc 4.1.2 } catch (abi::__forced_unwind&) { //pthread_exit and pthread_cancel will cause an abi::__forced_unwind to be thrown. Rethrow it. throw; -#endif -#endif -#endif - } catch (...) { - /* - In gcc 4.1.2 I cannot find the catch type for the pthread_cancel forced_unwind exception so I changed - the catch here to just rethrow all unknown exceptions. For the other architectures - we signal the main thread for an orderly shutdown. - */ -#ifdef __linux -#ifdef __GNUC__ -#if __GNUC__ == 4 && __GNUC_MINOR__ == 1 - throw; -#else - std::string except_file ; - std::string except_message ; - if ( curr_job != NULL ) { - except_file = curr_job->name ; - } else { - except_file = "somewhere in Executive::run" ; - } - except_message = "unknown error" ; - fprintf(stderr, "\nExecutive::loop terminated with unknown exception\n ROUTINE: %s\n DIAGNOSTIC: %s\n" - " STOP TIME: %f\n" , except_file.c_str() , except_message.c_str() , exec_get_sim_time()) ; - exit(-1) ; -#endif -#endif #endif }