Commit 175b0632 authored by Pavel Vainerman's avatar Pavel Vainerman

(Activator): защита от зависания процесса делающего stack trace

parent 49499169
...@@ -51,6 +51,14 @@ void TestProc::sysCommand( const UniSetTypes::SystemMessage* sm ) ...@@ -51,6 +51,14 @@ void TestProc::sysCommand( const UniSetTypes::SystemMessage* sm )
} }
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
string TestProc::getMonitInfo()
{
int* p = 0;
(*p) = 10;
return "";
}
// -----------------------------------------------------------------------------
void TestProc::sensorInfo( const SensorMessage* sm ) void TestProc::sensorInfo( const SensorMessage* sm )
{ {
/* /*
......
...@@ -25,9 +25,10 @@ class TestProc: ...@@ -25,9 +25,10 @@ class TestProc:
}; };
virtual void step(); virtual void step();
virtual void sensorInfo( const UniSetTypes::SensorMessage* sm ); virtual void sensorInfo( const UniSetTypes::SensorMessage* sm ) override;
virtual void timerInfo( const UniSetTypes::TimerMessage* tm ); virtual void timerInfo( const UniSetTypes::TimerMessage* tm ) override;
virtual void sysCommand( const UniSetTypes::SystemMessage* sm ); virtual void sysCommand( const UniSetTypes::SystemMessage* sm ) override;
virtual std::string getMonitInfo() override;
void test_depend(); void test_depend();
void test_undefined_state(); void test_undefined_state();
......
...@@ -105,7 +105,7 @@ class OmniThreadCreator: ...@@ -105,7 +105,7 @@ class OmniThreadCreator:
{ {
exit(0); exit(0);
} }
inline pid_t getTID() inline int getTID()
{ {
return id(); return id();
} }
......
...@@ -120,7 +120,7 @@ class UniSetActivator: ...@@ -120,7 +120,7 @@ class UniSetActivator:
TerminateEvent_Signal s_term; TerminateEvent_Signal s_term;
std::atomic_bool omDestroy; std::atomic_bool omDestroy;
pid_t thpid; // pid orb потока pid_t thid; // id orb потока
bool _noUseGdbForStackTrace = { false }; bool _noUseGdbForStackTrace = { false };
......
...@@ -96,6 +96,7 @@ static std::atomic_bool g_term = ATOMIC_VAR_INIT(0); ...@@ -96,6 +96,7 @@ static std::atomic_bool g_term = ATOMIC_VAR_INIT(0);
static std::atomic_bool g_done = ATOMIC_VAR_INIT(0); static std::atomic_bool g_done = ATOMIC_VAR_INIT(0);
static std::atomic_bool g_work_stopped = ATOMIC_VAR_INIT(0); static std::atomic_bool g_work_stopped = ATOMIC_VAR_INIT(0);
static std::atomic_int g_signo = ATOMIC_VAR_INIT(0); static std::atomic_int g_signo = ATOMIC_VAR_INIT(0);
static std::atomic_bool g_trace_done = ATOMIC_VAR_INIT(0);
static std::mutex g_workmutex; static std::mutex g_workmutex;
static std::mutex g_termmutex; static std::mutex g_termmutex;
...@@ -104,12 +105,15 @@ static std::mutex g_finimutex; ...@@ -104,12 +105,15 @@ static std::mutex g_finimutex;
static std::condition_variable g_finievent; static std::condition_variable g_finievent;
static std::mutex g_donemutex; static std::mutex g_donemutex;
static std::condition_variable g_doneevent; static std::condition_variable g_doneevent;
static std::mutex g_trace_donemutex;
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 = 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;
static pid_t g_stacktrace_proc_pid = 0; // pid процесса делающего stack trace (для защиты от зависания)
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
// Чтобы не выделять память во время "вылета", // Чтобы не выделять память во время "вылета",
// выделим необходимое для stacktrace зараннее // выделим необходимое для stacktrace зараннее
...@@ -117,8 +121,10 @@ static const int KILL_TIMEOUT = 8; ...@@ -117,8 +121,10 @@ static const int KILL_TIMEOUT = 8;
#define FUNCNAMESIZE 256 #define FUNCNAMESIZE 256
#define MAXFRAMES 64 #define MAXFRAMES 64
// выделение специального стека заранее // выделение специального стека заранее
static char g_stack_body[MAXFRAMES*FUNCNAMESIZE+500]; // +60 - это на всякие переменные при обработке stack trace и т.п.
static char g_stack_body[(MAXFRAMES+60)*FUNCNAMESIZE];
static stack_t g_sigseg_stack; static stack_t g_sigseg_stack;
static void on_stacktrace_timeout(); // поток для защиты от зависания "процесса создания stack trace"
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
// код функции printStackTrace взят с https://oroboro.com/stack-trace-on-crash/ // код функции printStackTrace взят с https://oroboro.com/stack-trace-on-crash/
// будет работать только под LINUX (т.к. используется backtrace) // будет работать только под LINUX (т.к. используется backtrace)
...@@ -284,7 +290,11 @@ bool gdb_print_trace() ...@@ -284,7 +290,11 @@ bool gdb_print_trace()
else else
{ {
close(cp[1]); close(cp[1]);
char buf[5000];
g_stacktrace_proc_pid = child_pid;
std::thread t(on_stacktrace_timeout); // запускаем поток "защищающий" от зависания процесса создания stack trace
char buf[FUNCNAMESIZE]; // как минимум у нас есть буфер такого размера выделенный зараннее
while( true ) while( true )
{ {
ssize_t r = ::read(cp[0], &buf, sizeof(buf) - 1 ); ssize_t r = ::read(cp[0], &buf, sizeof(buf) - 1 );
...@@ -300,12 +310,34 @@ bool gdb_print_trace() ...@@ -300,12 +310,34 @@ bool gdb_print_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_doneevent.notify_all();
}
t.join();
} }
TRACELOG << "-----------------------------------------" << endl << flush; TRACELOG << "-----------------------------------------" << endl << flush;
return true; return true;
} }
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
static void on_stacktrace_timeout()
{
std::unique_lock<std::mutex> lk(g_trace_donemutex);
g_trace_doneevent.wait_for(lk, std::chrono::milliseconds(KILL_TIMEOUT * 1000), []()
{
return (g_trace_done == true);
} );
if( !g_trace_done )
{
ulogsys << "****** STACK TRACE TIMEOUT.. (kill process) *******" << endl << flush;
kill(g_stacktrace_proc_pid,SIGKILL);
}
}
// ------------------------------------------------------------------------------------------
static void activator_terminate( int signo ) static void activator_terminate( int signo )
{ {
if( g_term ) if( g_term )
...@@ -364,7 +396,7 @@ void finished_thread() ...@@ -364,7 +396,7 @@ void finished_thread()
ulogsys << "****** FINISHED END ****" << endl << flush; ulogsys << "****** FINISHED END ****" << endl << flush;
} }
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
void kill_thread() void on_finish_timeout()
{ {
std::unique_lock<std::mutex> lk(g_donemutex); std::unique_lock<std::mutex> lk(g_donemutex);
...@@ -411,7 +443,7 @@ void terminate_thread() ...@@ -411,7 +443,7 @@ void terminate_thread()
{ {
std::unique_lock<std::mutex> lk(g_donemutex); std::unique_lock<std::mutex> lk(g_donemutex);
g_done = false; g_done = false;
g_kill_thread = make_shared<std::thread>(kill_thread); g_kill_thread = make_shared<std::thread>(on_finish_timeout);
} }
if( g_act ) if( g_act )
...@@ -717,11 +749,11 @@ void UniSetActivator::work() ...@@ -717,11 +749,11 @@ void UniSetActivator::work()
try try
{ {
if( orbthr ) if( orbthr )
thpid = orbthr->getTID(); thid = orbthr->getTID();
else else
thpid = getpid(); thid = getpid();
g_term_thread = make_shared<std::thread>(terminate_thread ); g_term_thread = make_shared<std::thread>(terminate_thread);
omniORB::setMainThread(); omniORB::setMainThread();
orb->run(); orb->run();
} }
......
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