Commit 71329ec7 authored by Pavel Vainerman's avatar Pavel Vainerman

(UniSetActivator): вывод call trace в ulog[SYSTEM] для возможности

удалённого просмотра через LogServer
parent 7d947416
...@@ -29,13 +29,11 @@ ...@@ -29,13 +29,11 @@
#include <atomic> #include <atomic>
#include <chrono> #include <chrono>
// for print stacktrace // for stack trace
// -------------------- // --------------------
#include <execinfo.h> #include <execinfo.h>
#include <errno.h>
#include <cxxabi.h> #include <cxxabi.h>
#include <cstdio> #include <iomanip>
#include <cstdlib>
// -------------------- // --------------------
#include "Exceptions.h" #include "Exceptions.h"
...@@ -102,23 +100,41 @@ static const int TERMINATE_TIMEOUT = 3; // время отведенное на ...@@ -102,23 +100,41 @@ static const int TERMINATE_TIMEOUT = 3; // время отведенное на
static const int THREAD_TERMINATE_PAUSE = 500; // [мсек] пауза при завершении потока (см. work()) static const int THREAD_TERMINATE_PAUSE = 500; // [мсек] пауза при завершении потока (см. work())
static const int KILL_TIMEOUT = 8; static const int KILL_TIMEOUT = 8;
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
// Чтобы не выделять память во время "вылета",
// выделим необходимое для stacktrace зараннее
// ----------
#define FUNCNAMESIZE 256
static size_t funcnamesize = FUNCNAMESIZE;
static char funcname[FUNCNAMESIZE];
// storage array for stack trace address data
#define MAXFRAMES 64
static void* addrlist[MAXFRAMES];
// ------------------------------------------------------------------------------------------
// код функции printStackTrace взят с https://oroboro.com/stack-trace-on-crash/ // код функции printStackTrace взят с https://oroboro.com/stack-trace-on-crash/
// будет работать только под LINUX (т.к. используется backtrace) // будет работать только под LINUX (т.к. используется backtrace)
// Как альтернативу, можно применить libunwind // Как альтернативу, можно применить libunwind
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
static inline void printStackTrace( FILE *out = stderr, unsigned int max_frames = 31 ) // Выводим используя ulog() чтобы можно было удалённо увидеть через LogServer
// (хотя конечно это как повезёт и зависит от того где собственно произошла ошибка)
// ------------------------------------------------------------------------------------------
static inline void printStackTrace()
{ {
fprintf(out, "stack trace:\n"); auto log = ulog();
if( !log )
return;
if( !log->is_system() )
return;
// storage array for stack trace address data log->system() << "stack trace:\n";
void* addrlist[max_frames+1];
// retrieve current stack addresses // retrieve current stack addresses
unsigned int addrlen = backtrace( addrlist, sizeof( addrlist ) / sizeof( void* )); unsigned int addrlen = backtrace(addrlist, MAXFRAMES);
if ( addrlen == 0 ) if ( addrlen == 0 )
{ {
fprintf( out, " \n" ); log->system() << "...empty stack..\n";
return; return;
} }
...@@ -127,9 +143,7 @@ static inline void printStackTrace( FILE *out = stderr, unsigned int max_frames ...@@ -127,9 +143,7 @@ static inline void printStackTrace( FILE *out = stderr, unsigned int max_frames
// this array must be free()-ed // this array must be free()-ed
char** symbollist = backtrace_symbols( addrlist, addrlen ); char** symbollist = backtrace_symbols( addrlist, addrlen );
#define FUNCNAMESIZE 256 log->system() << std::left;
size_t funcnamesize = FUNCNAMESIZE;
char funcname[FUNCNAMESIZE];
// iterate over the returned symbol lines. skip the first, it is the // iterate over the returned symbol lines. skip the first, it is the
// address of this function. // address of this function.
...@@ -140,7 +154,7 @@ static inline void printStackTrace( FILE *out = stderr, unsigned int max_frames ...@@ -140,7 +154,7 @@ static inline void printStackTrace( FILE *out = stderr, unsigned int max_frames
char* end_offset = NULL; char* end_offset = NULL;
// find parentheses and +address offset surrounding the mangled name // find parentheses and +address offset surrounding the mangled name
for ( char *p = symbollist[i]; *p; ++p ) for ( char* p = symbollist[i]; *p; ++p )
{ {
if ( *p == '(' ) if ( *p == '(' )
begin_name = p; begin_name = p;
...@@ -154,6 +168,7 @@ static inline void printStackTrace( FILE *out = stderr, unsigned int max_frames ...@@ -154,6 +168,7 @@ static inline void printStackTrace( FILE *out = stderr, unsigned int max_frames
{ {
*begin_name++ = '\0'; *begin_name++ = '\0';
*end_offset++ = '\0'; *end_offset++ = '\0';
if ( begin_offset ) if ( begin_offset )
*begin_offset++ = '\0'; *begin_offset++ = '\0';
...@@ -165,24 +180,36 @@ static inline void printStackTrace( FILE *out = stderr, unsigned int max_frames ...@@ -165,24 +180,36 @@ static inline void printStackTrace( FILE *out = stderr, unsigned int max_frames
char* ret = abi::__cxa_demangle( begin_name, funcname, char* ret = abi::__cxa_demangle( begin_name, funcname,
&funcnamesize, &status ); &funcnamesize, &status );
char* fname = begin_name; char* fname = begin_name;
if ( status == 0 ) if ( status == 0 )
fname = ret; fname = ret;
if ( begin_offset ) if ( begin_offset )
{ {
fprintf( out, " %-30s ( %-40s + %-6s) %s\n", log->system() << setw(30) << symbollist[i]
symbollist[i], fname, begin_offset, end_offset ); << " ( " << setw(40) << fname
} else { << " +" << setw(6) << begin_offset
fprintf( out, " %-30s ( %-40s %-6s) %s\n", << ") " << end_offset
symbollist[i], fname, "", end_offset ); << endl;
}
else
{
log->system() << setw(30) << symbollist[i]
<< " ( " << setw(40) << fname
<< " " << setw(6) << ""
<< ") " << end_offset
<< endl;
} }
} else { }
else
{
// couldn't parse the line? print the whole line. // couldn't parse the line? print the whole line.
fprintf(out, " %-40s\n", symbollist[i]); log->system() << setw(40) << symbollist[i] << endl;
} }
} }
std::free(symbollist); std::free(symbollist);
log->system() << endl << "..end of trace.." << endl << flush;
} }
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
static void activator_terminate( int signo ) static void activator_terminate( int signo )
...@@ -210,12 +237,18 @@ static void activator_terminate( int signo ) ...@@ -210,12 +237,18 @@ static void activator_terminate( int signo )
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
static void activator_terminate_with_calltrace( int signo ) static void activator_terminate_with_calltrace( int signo )
{ {
ulogsys << "****** TERMINATE signo=" << signo << " WITH CALL TRACE" << endl << flush; printStackTrace();
// т.к. это SIGSEGV, то просто вылетаем по умолчанию..
signal(signo, SIG_DFL);
raise(signo);
#if 0
if( g_term ) if( g_term )
return; return;
printStackTrace(); printStackTrace();
activator_terminate(signo); activator_terminate(signo);
#endif
} }
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
void finished_thread() void finished_thread()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment