mirror of
https://github.com/nasa/trick.git
synced 2024-12-24 07:16:41 +00:00
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
This commit is contained in:
parent
d6e01ee1c4
commit
03d6105c6c
@ -65,6 +65,9 @@ namespace Trick {
|
|||||||
/** Allows the trapping of SIGSEGV signals and graceful shutdown.\n */
|
/** Allows the trapping of SIGSEGV signals and graceful shutdown.\n */
|
||||||
bool trap_sigsegv; /**< trick_units(--) */
|
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 */
|
/** Flags a restart was loaded\n */
|
||||||
bool restart_called; /**< trick_io(**) trick_units(--) */
|
bool restart_called; /**< trick_io(**) trick_units(--) */
|
||||||
|
|
||||||
@ -512,6 +515,14 @@ namespace Trick {
|
|||||||
*/
|
*/
|
||||||
bool get_trap_sigsegv() ;
|
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.
|
@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.
|
@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) ;
|
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.
|
@userdesc Command to get the simulation time in seconds.
|
||||||
Formula for simulation time is time_tics / time_tic_value.
|
Formula for simulation time is time_tics / time_tic_value.
|
||||||
|
@ -57,6 +57,7 @@ Trick::Executive::Executive() {
|
|||||||
trap_sigbus = false ;
|
trap_sigbus = false ;
|
||||||
trap_sigfpe = false ;
|
trap_sigfpe = false ;
|
||||||
trap_sigsegv = false ;
|
trap_sigsegv = false ;
|
||||||
|
trap_sigabrt = false ;
|
||||||
|
|
||||||
build_date = std::string("unknown") ;
|
build_date = std::string("unknown") ;
|
||||||
current_version = std::string("unknown") ;
|
current_version = std::string("unknown") ;
|
||||||
@ -257,6 +258,10 @@ bool Trick::Executive::get_trap_sigsegv() {
|
|||||||
return(trap_sigsegv) ;
|
return(trap_sigsegv) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Trick::Executive::get_trap_sigabrt() {
|
||||||
|
return(trap_sigabrt) ;
|
||||||
|
}
|
||||||
|
|
||||||
void Trick::Executive::reset_job_cycle_times() {
|
void Trick::Executive::reset_job_cycle_times() {
|
||||||
unsigned int ii ;
|
unsigned int ii ;
|
||||||
for ( ii = 0 ; ii < all_jobs_vector.size() ; ii++ ) {
|
for ( ii = 0 ; ii < all_jobs_vector.size() ; ii++ ) {
|
||||||
|
@ -378,6 +378,18 @@ extern "C" int exec_get_trap_sigsegv() {
|
|||||||
return -1 ;
|
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 ------------------------
|
// -------------------------- SET ------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -593,6 +605,18 @@ extern "C" int exec_set_trap_sigsegv( int on_off ) {
|
|||||||
return -1 ;
|
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
|
* @relates Trick::Executive
|
||||||
* @copydoc Trick::Executive::set_job_onoff
|
* @copydoc Trick::Executive::set_job_onoff
|
||||||
|
@ -62,25 +62,6 @@ int Trick::Executive::init() {
|
|||||||
except_file = ex.file ;
|
except_file = ex.file ;
|
||||||
except_message = ex.message ;
|
except_message = ex.message ;
|
||||||
return(-1) ;
|
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. */
|
/* return 0 if there are no errors. */
|
||||||
|
@ -112,7 +112,32 @@ int Trick::Executive::set_trap_sigsegv(bool on_off) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
@details
|
@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.
|
-# Assign ctrl_c_hand() as the signal handler for SIGINT.
|
||||||
Requirement [@ref r_exec_signal_0].
|
Requirement [@ref r_exec_signal_0].
|
||||||
-# Assign sig_hand() as the signal handler for SIGTERM.
|
-# 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_sigbus(true) ;
|
||||||
set_trap_sigfpe(false) ;
|
set_trap_sigfpe(false) ;
|
||||||
set_trap_sigsegv(true) ;
|
set_trap_sigsegv(true) ;
|
||||||
|
set_trap_sigabrt(true) ;
|
||||||
|
|
||||||
/* Assign ctrl_c_hand() as the default signal handler for SIGINT (<CTRL-C> keypress). */
|
/* Assign ctrl_c_hand() as the default signal handler for SIGINT (<CTRL-C> keypress). */
|
||||||
sigact.sa_handler = (void (*)(int)) ctrl_c_hand;
|
sigact.sa_handler = (void (*)(int)) ctrl_c_hand;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <exception>
|
||||||
#include "trick/Executive.hh"
|
#include "trick/Executive.hh"
|
||||||
#include "trick/ExecutiveException.hh"
|
#include "trick/ExecutiveException.hh"
|
||||||
|
|
||||||
@ -52,26 +53,6 @@ int Trick::Executive::loop() {
|
|||||||
except_file = ex.file ;
|
except_file = ex.file ;
|
||||||
except_message = ex.message ;
|
except_message = ex.message ;
|
||||||
return(ex.ret_code) ;
|
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. */
|
/* return 0 if there are no errors. */
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
#include "trick/message_proto.h"
|
#include "trick/message_proto.h"
|
||||||
|
|
||||||
int Trick::Executive::set_thread_rt_semaphores(unsigned int thread_id , bool yes_no) {
|
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"
|
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)") ;
|
"Use exec_get_thread(thread_id).set_trigger_type(Trick::ThreadTriggerType tt_type)") ;
|
||||||
return -1 ;
|
return -1 ;
|
||||||
|
@ -73,19 +73,6 @@ int Trick::Executive::shutdown() {
|
|||||||
except_return = ex.ret_code ;
|
except_return = ex.ret_code ;
|
||||||
except_file += std::string(" then exception caught in ") + ex.file ;
|
except_file += std::string(" then exception caught in ") + ex.file ;
|
||||||
except_message += std::string(" then exception Message: ") + ex.message ;
|
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);
|
getrusage(RUSAGE_SELF, &cpu_usage_buf);
|
||||||
|
@ -45,6 +45,9 @@ void Trick::Executive::signal_handler(int sig) {
|
|||||||
case SIGSEGV: /* Segmentation fault */
|
case SIGSEGV: /* Segmentation fault */
|
||||||
write( 2 , "SIGSEGV" , 7 ) ;
|
write( 2 , "SIGSEGV" , 7 ) ;
|
||||||
break;
|
break;
|
||||||
|
case SIGABRT: /* Abort */
|
||||||
|
write( 2 , "SIGABRT" , 7 ) ;
|
||||||
|
break;
|
||||||
default: /* Unrecognized signal */
|
default: /* Unrecognized signal */
|
||||||
write( 2 , "unknown" , 7 ) ;
|
write( 2 , "unknown" , 7 ) ;
|
||||||
break;
|
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());
|
sprintf(command, "%s -silent /proc/%d/exe %d", debugger_command.c_str(), getpid(), getpid());
|
||||||
system(command);
|
system(command);
|
||||||
} else if (stack_trace == true ) {
|
} 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());
|
"/proc/%d/exe %d | grep -A 20 \"signal handler\"", debugger_command.c_str(), getpid(), getpid());
|
||||||
system(command);
|
system(command);
|
||||||
}
|
}
|
||||||
|
@ -218,51 +218,11 @@ void * Trick::Threads::thread_body() {
|
|||||||
" THREAD STOP TIME: %f\n" ,
|
" THREAD STOP TIME: %f\n" ,
|
||||||
thread_id, ex.file.c_str(), ex.message.c_str(), exec_get_sim_time()) ;
|
thread_id, ex.file.c_str(), ex.message.c_str(), exec_get_sim_time()) ;
|
||||||
exit(ex.ret_code) ;
|
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 __linux
|
||||||
#ifdef __GNUC__
|
|
||||||
#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 2
|
|
||||||
// for post gcc 4.1.2
|
// for post gcc 4.1.2
|
||||||
} catch (abi::__forced_unwind&) {
|
} catch (abi::__forced_unwind&) {
|
||||||
//pthread_exit and pthread_cancel will cause an abi::__forced_unwind to be thrown. Rethrow it.
|
//pthread_exit and pthread_cancel will cause an abi::__forced_unwind to be thrown. Rethrow it.
|
||||||
throw;
|
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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user