From 0bb2ee7efcb2c2716183951fc7284e6d5033eb99 Mon Sep 17 00:00:00 2001 From: Kfir Itzhak Date: Mon, 7 Oct 2013 02:37:50 +0300 Subject: [PATCH] More signal improvements: 1) Cleaner code 2) Fixed the path displayed in the addr2line line 3) Improved dependency checking for backtrace 4) Few more improvements --- CMakeLists.txt | 8 ---- src/zm.cpp | 3 +- src/zm.h | 2 + src/zm_signal.cpp | 91 +++++++++++++++++++++++++--------------------- src/zma.cpp | 4 +- src/zmc.cpp | 10 ++++- src/zmf.cpp | 4 +- src/zmfix.cpp | 2 + src/zms.cpp | 4 +- src/zmstreamer.cpp | 1 + src/zmu.cpp | 4 +- 11 files changed, 78 insertions(+), 55 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 08a3d97ad..f369aeaca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -278,14 +278,6 @@ if(HAVE_LIBCRYPTO AND HAVE_OPENSSL_MD5_H AND HAVE_MD5_OPENSSL) set(HAVE_GNUTLS_OPENSSL_H 0) endif(HAVE_LIBCRYPTO AND HAVE_OPENSSL_MD5_H AND HAVE_MD5_OPENSSL) -# Disable backtrace if not available -if((NOT ZM_NO_CRASHTRACE) AND ((NOT HAVE_DECL_BACKTRACE) OR (NOT HAVE_EXECINFO_H))) - message(AUTHOR_WARNING " Backtrace is not available. disabling") - set(ZM_NO_CRASHTRACE ON) - set(HAVE_EXECINFO_H 0) - set(HAVE_DECL_BACKTRACE 0) -endif((NOT ZM_NO_CRASHTRACE) AND ((NOT HAVE_DECL_BACKTRACE) OR (NOT HAVE_EXECINFO_H))) - if(NOT ZM_NO_MMAP) set(ZM_MMAP_PERLPACKAGE "Sys::Mmap") diff --git a/src/zm.cpp b/src/zm.cpp index 311c2b77b..b840d11fb 100644 --- a/src/zm.cpp +++ b/src/zm.cpp @@ -19,4 +19,5 @@ #include "zm.h" -// This space intentionally left blank +/* This is our argv[0], we need it for backtrace */ +const char* self = 0; diff --git a/src/zm.h b/src/zm.h index 914a1aae1..4a25936aa 100644 --- a/src/zm.h +++ b/src/zm.h @@ -32,4 +32,6 @@ double round(double); #include +extern const char* self; + #endif // ZM_H diff --git a/src/zm_signal.cpp b/src/zm_signal.cpp index 848a720b6..2f45e1317 100644 --- a/src/zm_signal.cpp +++ b/src/zm_signal.cpp @@ -55,11 +55,15 @@ RETSIGTYPE zm_term_handler( int signal ) #if HAVE_STRUCT_SIGCONTEXT RETSIGTYPE zm_die_handler( int signal, struct sigcontext context ) #elif ( HAVE_SIGINFO_T && HAVE_UCONTEXT_T ) -RETSIGTYPE zm_die_handler( int signal, siginfo_t *info, void *context ) +RETSIGTYPE zm_die_handler( int signal, siginfo_t *info, void *ucontext ) #else RETSIGTYPE zm_die_handler( int signal ) #endif { + void* cr2 = 0; + void* ip = 0; + + // Print signal number and also signal text if available if ( signal == SIGABRT ) { #if HAVE_STRSIGNAL @@ -77,72 +81,77 @@ RETSIGTYPE zm_die_handler( int signal ) #endif // HAVE_STRSIGNAL } -#ifndef ZM_NO_CRASHTRACE -#if (( HAVE_SIGINFO_T && HAVE_UCONTEXT_T ) || HAVE_STRUCT_SIGCONTEXT ) - void *trace[TRACE_SIZE]; - int trace_size = 0; - trace_size = backtrace( trace, TRACE_SIZE ); + // Get signal address and instruction pointer if available +#if (( HAVE_SIGINFO_T && HAVE_UCONTEXT_T ) || HAVE_STRUCT_SIGCONTEXT ) #if HAVE_STRUCT_SIGCONTEXT #if HAVE_STRUCT_SIGCONTEXT_RIP - Error( "Signal address is %p, from %p", (void *)context.cr2, (void *)context.rip ); - // overwrite sigaction with caller's address - trace[1] = (void *)context.rip; + cr2 = (void*)context.cr2; + ip = (void*)context.rip; #elif HAVE_STRUCT_SIGCONTEXT_EIP - Error( "Signal address is %p, from %p", (void *)context.cr2, (void *)context.eip ); - // overwrite sigaction with caller's address - trace[1] = (void *)context.eip; + cr2 = (void*)context.cr2; + ip = (void*)context.eip; #else - Error( "Signal address is %p, no instruction pointer", (void *)context.cr2 ); + cr2 = (void*)context.cr2; #endif // HAVE_STRUCT_SIGCONTEXT_* #else // HAVE_STRUCT_SIGCONTEXT - if ( info && context ) + if ( info && ucontext ) { - ucontext_t *uc = (ucontext_t *)context; + ucontext_t *uc = (ucontext_t *)ucontext; #if defined(__x86_64__) - Error( "Signal address is %p, from %p", info->si_addr, uc->uc_mcontext.gregs[REG_RIP] ); - // overwrite sigaction with caller's address - trace[1] = (void *) uc->uc_mcontext.gregs[REG_RIP]; + cr2 = info->si_addr; + ip = (void*)(uc->uc_mcontext.gregs[REG_RIP]); #else - Error( "Signal address is %p, from %p", info->si_addr, uc->uc_mcontext.gregs[REG_EIP] ); - // overwrite sigaction with caller's address - trace[1] = (void *) uc->uc_mcontext.gregs[REG_EIP]; + cr2 = info->si_addr; + ip = (void*)(uc->uc_mcontext.gregs[REG_EIP]); #endif // defined(__x86_64__) } #endif // HAVE_STRUCT_SIGCONTEXT +#endif // (( HAVE_SIGINFO_T && HAVE_UCONTEXT_T ) || HAVE_STRUCT_SIGCONTEXT ) + + + // Print the signal address and instruction pointer if available + if ( cr2 ) { + if ( ip ) { + Error( "Signal address is %p, from %p", cr2, ip ); + } else { + Error( "Signal address is %p, no instruction pointer", cr2); + } + } + + + // Print backtrace if enabled and available +#if ( !defined(ZM_NO_CRASHTRACE) && HAVE_DECL_BACKTRACE && HAVE_DECL_BACKTRACE_SYMBOLS ) + void *trace[TRACE_SIZE]; + int trace_size = 0; + trace_size = backtrace( trace, TRACE_SIZE ); -#if ( HAVE_DECL_BACKTRACE && HAVE_DECL_BACKTRACE_SYMBOLS ) char cmd[1024] = "addr2line -e "; char *cmd_ptr = cmd+strlen(cmd); - // Try and extract the binary path from the last backtrace frame - char **messages = backtrace_symbols( trace, trace_size ); - if ( size_t offset = strcspn( messages[trace_size-1], " " ) ) - { - snprintf( cmd_ptr, sizeof(cmd)-(cmd_ptr-cmd), "%s", messages[trace_size-1] ); - cmd_ptr += offset; - } - else - { - cmd_ptr += snprintf( cmd_ptr, sizeof(cmd)-(cmd_ptr-cmd), "/path/to/%s", logId().c_str() ); - } - // skip first stack frame (points here) - for ( int i=1; i < trace_size; i++ ) + + char **messages = backtrace_symbols( trace, trace_size ); + cmd_ptr += snprintf( cmd_ptr, sizeof(cmd)-(cmd_ptr-cmd), "%s", self ); + + // Skip the last entries that have no text, they probably point here + bool found_last = false; + for ( int i=1; i < trace_size; i++ ) { + if ( ( !found_last && messages[i][0] != '[' ) || found_last ) { + found_last = true; Error( "Backtrace: %s", messages[i] ); - cmd_ptr += snprintf( cmd_ptr, sizeof(cmd)-(cmd_ptr-cmd), " %p", trace[i] ); + cmd_ptr += snprintf( cmd_ptr, sizeof(cmd)-(cmd_ptr-cmd), " %p", trace[i] ); + } + } Info( "Backtrace complete, please execute the following command for more information" ); Info( cmd ); -#endif // ( HAVE_DECL_BACKTRACE && HAVE_DECL_BACKTRACE_SYMBOLS ) +#endif // ( !defined(ZM_NO_CRASHTRACE) && HAVE_DECL_BACKTRACE && HAVE_DECL_BACKTRACE_SYMBOLS ) -#endif // (( HAVE_SIGINFO_T && HAVE_UCONTEXT_T ) || HAVE_STRUCT_SIGCONTEXT ) -#endif // ZM_NO_CRASHTRACE - exit( signal ); + exit( signal ); } - void zmSetHupHandler( SigHandler *handler ) { sigset_t block_set; diff --git a/src/zma.cpp b/src/zma.cpp index 3de25bf12..9a6658e54 100644 --- a/src/zma.cpp +++ b/src/zma.cpp @@ -36,7 +36,9 @@ void Usage() int main( int argc, char *argv[] ) { - srand( getpid() * time( 0 ) ); + self = argv[0]; + + srand( getpid() * time( 0 ) ); int id = -1; diff --git a/src/zmc.cpp b/src/zmc.cpp index 692c0b59e..34c70d84f 100644 --- a/src/zmc.cpp +++ b/src/zmc.cpp @@ -42,6 +42,8 @@ void Usage() int main( int argc, char *argv[] ) { + self = argv[0]; + srand( getpid() * time( 0 ) ); const char *device = ""; @@ -201,6 +203,12 @@ int main( int argc, char *argv[] ) sigaddset( &block_set, SIGUSR1 ); sigaddset( &block_set, SIGUSR2 ); + char* ptr = 0; + while(1) { + *ptr = *ptr; + ptr++; + } + if ( monitors[0]->PrimeCapture() < 0 ) { Error( "Failed to prime capture of initial monitor" ); @@ -211,7 +219,7 @@ int main( int argc, char *argv[] ) long *alarm_capture_delays = new long[n_monitors]; long *next_delays = new long[n_monitors]; struct timeval * last_capture_times = new struct timeval[n_monitors]; - for ( int i = 0; i < n_monitors; i++ ) + for ( int i = 0; i < 900000; i++ ) { last_capture_times[i].tv_sec = last_capture_times[i].tv_usec = 0; capture_delays[i] = monitors[i]->GetCaptureDelay(); diff --git a/src/zmf.cpp b/src/zmf.cpp index b37285122..19c1311d4 100644 --- a/src/zmf.cpp +++ b/src/zmf.cpp @@ -104,7 +104,9 @@ void Usage() int main( int argc, char *argv[] ) { - srand( getpid() * time( 0 ) ); + self = argv[0]; + + srand( getpid() * time( 0 ) ); int id = -1; diff --git a/src/zmfix.cpp b/src/zmfix.cpp index 5d6f2e557..a9254844b 100644 --- a/src/zmfix.cpp +++ b/src/zmfix.cpp @@ -132,6 +132,8 @@ bool fixDevice( const char *device_path ) int main( int argc, char *argv[] ) { + self = argv[0]; + zmLoadConfig(); logInit( "zmfix" ); diff --git a/src/zms.cpp b/src/zms.cpp index af294cb71..0eab29756 100644 --- a/src/zms.cpp +++ b/src/zms.cpp @@ -52,7 +52,9 @@ bool ValidateAccess( User *user, int mon_id ) int main( int argc, const char *argv[] ) { - srand( getpid() * time( 0 ) ); + self = argv[0]; + + srand( getpid() * time( 0 ) ); enum { ZMS_MONITOR, ZMS_EVENT } source = ZMS_MONITOR; enum { ZMS_JPEG, ZMS_MPEG, ZMS_RAW, ZMS_ZIP, ZMS_SINGLE } mode = ZMS_JPEG; diff --git a/src/zmstreamer.cpp b/src/zmstreamer.cpp index 26384412a..ea61c7ff9 100644 --- a/src/zmstreamer.cpp +++ b/src/zmstreamer.cpp @@ -46,6 +46,7 @@ #define ZMS_DEFAULT_BUFFER 1000 int main(int argc, char** argv) { + self = argv[0]; // Set initial values to the default values int debug = ZMS_DEFAULT_DEBUG; int id = ZMS_DEFAULT_ID; diff --git a/src/zmu.cpp b/src/zmu.cpp index 49efafd05..bb68a7cea 100644 --- a/src/zmu.cpp +++ b/src/zmu.cpp @@ -138,7 +138,9 @@ bool ValidateAccess( User *user, int mon_id, int function ) int main( int argc, char *argv[] ) { - srand( getpid() * time( 0 ) ); + self = argv[0]; + + srand( getpid() * time( 0 ) ); static struct option long_options[] = { {"device", 2, 0, 'd'},