Commit 7ea7bb95 authored by Pavel Vainerman's avatar Pavel Vainerman

(UActivator): Пока что убрал pipe, т.к. приводит к зависанию на получении

stack trace.
parent 175b0632
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
Name: libuniset2 Name: libuniset2
Version: 2.4 Version: 2.4
Release: alt3 Release: alt3.1
Summary: UniSet - library for building distributed industrial control systems Summary: UniSet - library for building distributed industrial control systems
License: LGPL License: LGPL
...@@ -484,6 +484,9 @@ mv -f %buildroot%python_sitelibdir_noarch/* %buildroot%python_sitelibdir/%oname ...@@ -484,6 +484,9 @@ mv -f %buildroot%python_sitelibdir_noarch/* %buildroot%python_sitelibdir/%oname
# .. # ..
%changelog %changelog
* Thu Jul 28 2016 Pavel Vainerman <pv@altlinux.ru> 2.4-alt3.1
- test build
* Tue Jul 26 2016 Pavel Vainerman <pv@altlinux.ru> 2.4-alt3 * Tue Jul 26 2016 Pavel Vainerman <pv@altlinux.ru> 2.4-alt3
- merge devel/master - merge devel/master
......
#!/bin/sh #!/bin/sh
gdb --batch -n -ex "thread apply all bt" $1 $2 exec gdb --batch -n -ex "thread apply all bt" $1 $2
# | ssh xxxxxx # | ssh xxxxxx
# gcore $2 # gcore $2
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <signal.h> #include <signal.h>
#include <sstream> #include <sstream>
#include <fstream>
#include <condition_variable> #include <condition_variable>
#include <thread> #include <thread>
...@@ -110,9 +111,9 @@ static std::condition_variable g_trace_doneevent; ...@@ -110,9 +111,9 @@ static std::condition_variable g_trace_doneevent;
static std::shared_ptr<std::thread> g_term_thread; static std::shared_ptr<std::thread> g_term_thread;
static std::shared_ptr<std::thread> g_fini_thread; static std::shared_ptr<std::thread> g_fini_thread;
static std::shared_ptr<std::thread> g_kill_thread; static std::shared_ptr<std::thread> g_kill_thread;
static const int TERMINATE_TIMEOUT = 3; // время отведенное на завершение процесса [сек] static const int TERMINATE_TIMEOUT_SEC = 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_SEC = 8;
static pid_t g_stacktrace_proc_pid = 0; // pid процесса делающего stack trace (для защиты от зависания) static pid_t g_stacktrace_proc_pid = 0; // pid процесса делающего stack trace (для защиты от зависания)
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
// Чтобы не выделять память во время "вылета", // Чтобы не выделять память во время "вылета",
...@@ -123,6 +124,7 @@ static pid_t g_stacktrace_proc_pid = 0; // pid процесса делающег ...@@ -123,6 +124,7 @@ static pid_t g_stacktrace_proc_pid = 0; // pid процесса делающег
// выделение специального стека заранее // выделение специального стека заранее
// +60 - это на всякие переменные при обработке stack trace и т.п. // +60 - это на всякие переменные при обработке stack trace и т.п.
static char g_stack_body[(MAXFRAMES+60)*FUNCNAMESIZE]; static char g_stack_body[(MAXFRAMES+60)*FUNCNAMESIZE];
static char trace_buf[10000];
static stack_t g_sigseg_stack; static stack_t g_sigseg_stack;
static void on_stacktrace_timeout(); // поток для защиты от зависания "процесса создания stack trace" static void on_stacktrace_timeout(); // поток для защиты от зависания "процесса создания stack trace"
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
...@@ -247,13 +249,7 @@ bool gdb_print_trace() ...@@ -247,13 +249,7 @@ bool gdb_print_trace()
char name_buf[512]; char name_buf[512];
name_buf[readlink("/proc/self/exe", name_buf, 511)]=0; name_buf[readlink("/proc/self/exe", name_buf, 511)]=0;
// Чтобы перенаправить вывод в свой log, делаем pipe TRACELOG << "stack trace: for " << name_buf << " pid=" << pid_buf << endl;
int cp[2]; /* Child to parent pipe */
if( pipe(cp) < 0)
{
perror("Can't make pipe");
return false;
}
int child_pid = fork(); int child_pid = fork();
...@@ -263,18 +259,12 @@ bool gdb_print_trace() ...@@ -263,18 +259,12 @@ bool gdb_print_trace()
return false; return false;
} }
if (!child_pid) { if( child_pid == 0 ) // CHILD
{
close(cp[0]); msleep(300); // пауза чтобы родитель успел подготовиться..
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;
if( g_act && !g_act->getAbortScript().empty() ) if( g_act && !g_act->getAbortScript().empty() )
{ {
TRACELOG << "run abort script " << g_act->getAbortScript() << endl;
execlp(g_act->getAbortScript().c_str(), g_act->getAbortScript().c_str(), name_buf, pid_buf, NULL); execlp(g_act->getAbortScript().c_str(), g_act->getAbortScript().c_str(), name_buf, pid_buf, NULL);
} }
else else
...@@ -284,38 +274,24 @@ bool gdb_print_trace() ...@@ -284,38 +274,24 @@ bool gdb_print_trace()
execlp("gdb", "gdb", "--batch", "-n", "-ex", "thread apply all bt", name_buf, pid_buf, NULL); execlp("gdb", "gdb", "--batch", "-n", "-ex", "thread apply all bt", name_buf, pid_buf, NULL);
} }
//abort(); /* If gdb failed to start */ // abort(); /* If gdb failed to start */
return false; return false;
} }
else else // PARENT
{ {
close(cp[1]); if( g_act && !g_act->getAbortScript().empty() )
g_stacktrace_proc_pid = child_pid;
std::thread t(on_stacktrace_timeout); // запускаем поток "защищающий" от зависания процесса создания stack trace
char buf[FUNCNAMESIZE]; // как минимум у нас есть буфер такого размера выделенный зараннее
while( true )
{
ssize_t r = ::read(cp[0], &buf, sizeof(buf) - 1 );
if( r > 0 )
{ {
buf[r] = '\0'; TRACELOG << "stack trace: run script " << g_act->getAbortScript() << endl;
TRACELOG << buf;
continue;
} }
break; g_stacktrace_proc_pid = child_pid;
} g_trace_done = false;
std::thread t(on_stacktrace_timeout); // запускаем поток "защищающий" от зависания процесса создания stack trace
waitpid(child_pid,NULL,0); waitpid(child_pid,NULL,0);
{
std::unique_lock<std::mutex> lk(g_trace_donemutex);
g_trace_done = true; g_trace_done = true;
g_trace_doneevent.notify_all(); g_trace_doneevent.notify_all();
}
t.join(); t.join();
} }
...@@ -325,8 +301,10 @@ bool gdb_print_trace() ...@@ -325,8 +301,10 @@ bool gdb_print_trace()
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
static void on_stacktrace_timeout() static void on_stacktrace_timeout()
{ {
ulogsys << "****** STACK TRACE guard thread start (for pid=" << g_stacktrace_proc_pid << ") ******" << endl << flush;
std::unique_lock<std::mutex> lk(g_trace_donemutex); std::unique_lock<std::mutex> lk(g_trace_donemutex);
g_trace_doneevent.wait_for(lk, std::chrono::milliseconds(KILL_TIMEOUT * 1000), []()
g_trace_doneevent.wait_for(lk, std::chrono::milliseconds(KILL_TIMEOUT_SEC * 1000), []()
{ {
return (g_trace_done == true); return (g_trace_done == true);
} ); } );
...@@ -336,6 +314,8 @@ static void on_stacktrace_timeout() ...@@ -336,6 +314,8 @@ static void on_stacktrace_timeout()
ulogsys << "****** STACK TRACE TIMEOUT.. (kill process) *******" << endl << flush; ulogsys << "****** STACK TRACE TIMEOUT.. (kill process) *******" << endl << flush;
kill(g_stacktrace_proc_pid,SIGKILL); kill(g_stacktrace_proc_pid,SIGKILL);
} }
else
ulogsys << "****** STACK TRACE guard thread finish ******" << endl << flush;
} }
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
static void activator_terminate( int signo ) static void activator_terminate( int signo )
...@@ -389,7 +369,7 @@ void finished_thread() ...@@ -389,7 +369,7 @@ void finished_thread()
g_finished = true; g_finished = true;
std::unique_lock<std::mutex> lkw(g_workmutex); std::unique_lock<std::mutex> lkw(g_workmutex);
g_finievent.wait_for(lkw, std::chrono::milliseconds(TERMINATE_TIMEOUT * 1000), []() g_finievent.wait_for(lkw, std::chrono::milliseconds(TERMINATE_TIMEOUT_SEC * 1000), []()
{ {
return (g_work_stopped == true); return (g_work_stopped == true);
} ); } );
...@@ -403,7 +383,7 @@ void on_finish_timeout() ...@@ -403,7 +383,7 @@ void on_finish_timeout()
if( g_done ) if( g_done )
return; return;
g_doneevent.wait_for(lk, std::chrono::milliseconds(KILL_TIMEOUT * 1000), []() g_doneevent.wait_for(lk, std::chrono::milliseconds(KILL_TIMEOUT_SEC * 1000), []()
{ {
return (g_done == true); return (g_done == true);
} ); } );
...@@ -851,14 +831,16 @@ void UniSetActivator::set_signals(bool ask) ...@@ -851,14 +831,16 @@ void UniSetActivator::set_signals(bool ask)
sigemptyset(&act.sa_mask); sigemptyset(&act.sa_mask);
sigaddset(&act.sa_mask, SIGSEGV); sigaddset(&act.sa_mask, SIGSEGV);
act.sa_flags = 0; act.sa_flags = 0;
act.sa_flags |= SA_RESTART; // act.sa_flags |= SA_RESTART;
act.sa_flags |= SA_RESETHAND; act.sa_flags |= SA_RESETHAND;
#if 1
g_sigseg_stack.ss_sp = g_stack_body; g_sigseg_stack.ss_sp = g_stack_body;
g_sigseg_stack.ss_flags = SS_ONSTACK; g_sigseg_stack.ss_flags = SS_ONSTACK;
g_sigseg_stack.ss_size = sizeof(g_stack_body); g_sigseg_stack.ss_size = sizeof(g_stack_body);
assert(!sigaltstack(&g_sigseg_stack, nullptr)); assert(!sigaltstack(&g_sigseg_stack, nullptr));
act.sa_flags |= SA_ONSTACK; act.sa_flags |= SA_ONSTACK;
#endif
if(ask) if(ask)
act.sa_handler = activator_terminate_with_calltrace; act.sa_handler = activator_terminate_with_calltrace;
......
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