Commit 2b70dc45 authored by Pavel Vainerman's avatar Pavel Vainerman

(UniSetActivator): вторая версия механизма создания stacktrace.

Делается через gdb, если не получается то самостоятельно (backtrace). При этом можно отключить создание через gdb при помоши --uniset-no-use-gdb-for-stacktrace
parent 623c9055
...@@ -44,8 +44,9 @@ typedef std::shared_ptr<UniSetActivator> UniSetActivatorPtr; ...@@ -44,8 +44,9 @@ typedef std::shared_ptr<UniSetActivator> UniSetActivatorPtr;
auto act = UniSetActivator::Instance() auto act = UniSetActivator::Instance()
... ...
\endcode \endcode
* Активатор в свою очередь сам является менеджером(и объектом) и обладает всеми его свойствами * Активатор в свою очередь сам является менеджером(и объектом) и обладает всеми его свойствами
* *
* --uniset-no-use-gdb-for-stacktrace - НЕ ИСПОЛЬЗОВАТЬ gdb для stacktrace
*/ */
class UniSetActivator: class UniSetActivator:
public UniSetManager public UniSetManager
...@@ -74,6 +75,11 @@ class UniSetActivator: ...@@ -74,6 +75,11 @@ class UniSetActivator:
typedef sigc::signal<void, int> TerminateEvent_Signal; typedef sigc::signal<void, int> TerminateEvent_Signal;
TerminateEvent_Signal signal_terminate_event(); TerminateEvent_Signal signal_terminate_event();
inline bool noUseGdbForStackTrace()
{
return _noUseGdbForStackTrace;
}
protected: protected:
virtual void work(); virtual void work();
...@@ -109,6 +115,8 @@ class UniSetActivator: ...@@ -109,6 +115,8 @@ class UniSetActivator:
std::atomic_bool omDestroy; std::atomic_bool omDestroy;
pid_t thpid; // pid orb потока pid_t thpid; // pid orb потока
bool _noUseGdbForStackTrace = { false };
}; };
//---------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------
#endif #endif
......
...@@ -228,6 +228,76 @@ static inline void printStackTrace() ...@@ -228,6 +228,76 @@ static inline void printStackTrace()
TRACELOG << "-----------------------------------------" << endl << flush; TRACELOG << "-----------------------------------------" << endl << flush;
} }
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
// за основу взят код функции отсюда https://habrahabr.ru/company/ispsystem/blog/144198/
bool gdb_print_trace()
{
auto log = ulog();
// если логи отключены, то и выводить будем в cerr
bool to_cerr = ( !log || !log->is_system() );
char pid_buf[30];
sprintf(pid_buf, "%d", getpid());
char name_buf[512];
name_buf[readlink("/proc/self/exe", name_buf, 511)]=0;
// Чтобы перенаправить вывод в свой log, делаем pipe
int cp[2]; /* Child to parent pipe */
if( pipe(cp) < 0)
{
perror("Can't make pipe");
return false;
}
int child_pid = fork();
if( child_pid == -1 )
{
perror("Can't fork...");
return false;
}
if (!child_pid) {
close(cp[0]);
close( fileno(stdout) );
dup2(cp[1], fileno(stdout));
close( fileno(stderr) );
dup2(fileno(stdout), fileno(stderr));
TRACELOG << "stack trace for " << name_buf << " pid=" << pid_buf << endl;
// приходится выводить информацию по всем потокам, т.к. мы не знаем в каком сработал сигнал
// его надо смотреть по выводу "<signal handler called>"
execlp("gdb", "gdb", "--batch", "-n", "-ex", "thread apply all bt", name_buf, pid_buf, NULL);
//abort(); /* If gdb failed to start */
return false;
}
else
{
close(cp[1]);
char buf[5000];
while( true )
{
ssize_t r = ::read(cp[0], &buf, sizeof(buf) - 1 );
if( r > 0 )
{
buf[r] = '\0';
TRACELOG << buf;
continue;
}
break;
}
waitpid(child_pid,NULL,0);
}
TRACELOG << "-----------------------------------------" << endl << flush;
return true;
}
// ------------------------------------------------------------------------------------------
static void activator_terminate( int signo ) static void activator_terminate( int signo )
{ {
if( g_term ) if( g_term )
...@@ -238,7 +308,15 @@ static void activator_terminate( int signo ) ...@@ -238,7 +308,15 @@ static void activator_terminate( int signo )
g_term = true; g_term = true;
if( signo == SIGABRT ) if( signo == SIGABRT )
printStackTrace(); {
if( g_act && !g_act->noUseGdbForStackTrace() )
{
if( !gdb_print_trace() )
printStackTrace(); // пробуем сами..
}
else
printStackTrace();
}
ulogsys << "****** TERMINATE NOTIFY...(signo=" << signo << ")" << endl << flush; ulogsys << "****** TERMINATE NOTIFY...(signo=" << signo << ")" << endl << flush;
g_signo = signo; g_signo = signo;
...@@ -247,18 +325,17 @@ static void activator_terminate( int signo ) ...@@ -247,18 +325,17 @@ static void activator_terminate( int signo )
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
static void activator_terminate_with_calltrace( int signo ) static void activator_terminate_with_calltrace( int signo )
{ {
printStackTrace(); if( g_act && !g_act->noUseGdbForStackTrace() )
{
if( !gdb_print_trace() )
printStackTrace(); // пробуем сами..
}
else
printStackTrace();
// т.к. это SIGSEGV, то просто вылетаем по умолчанию.. // т.к. это SIGSEGV, то просто вылетаем по умолчанию..
signal(signo, SIG_DFL); signal(signo, SIG_DFL);
raise(signo); raise(signo);
#if 0
if( g_term )
return;
printStackTrace();
activator_terminate(signo);
#endif
} }
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
void finished_thread() void finished_thread()
...@@ -454,6 +531,9 @@ void UniSetActivator::init() ...@@ -454,6 +531,9 @@ void UniSetActivator::init()
myname = "UniSetActivator"; myname = "UniSetActivator";
auto conf = uniset_conf(); auto conf = uniset_conf();
_noUseGdbForStackTrace = ( findArgParam("--uniset-no-use-gdb-for-stacktrace", conf->getArgc(), conf->getArgv()) != -1 );
orb = conf->getORB(); orb = conf->getORB();
CORBA::Object_var obj = orb->resolve_initial_references("RootPOA"); CORBA::Object_var obj = orb->resolve_initial_references("RootPOA");
PortableServer::POA_var root_poa = PortableServer::POA::_narrow(obj); PortableServer::POA_var root_poa = PortableServer::POA::_narrow(obj);
......
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