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 
This commit is contained in:
Alex Lin 2016-04-15 14:57:22 -05:00
parent d6e01ee1c4
commit 03d6105c6c
10 changed files with 86 additions and 94 deletions

@ -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 <my_int> = 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(<on_off>) @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.

@ -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++ ) {

@ -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

@ -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. */

@ -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 (<CTRL-C> keypress). */
sigact.sa_handler = (void (*)(int)) ctrl_c_hand;

@ -1,6 +1,7 @@
#include <stdlib.h>
#include <exception>
#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. */

@ -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 ;

@ -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);

@ -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);
}

@ -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
}