Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
U
uniset2
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
1
Issues
1
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
UniSet project repositories
uniset2
Commits
ce6224ef
Commit
ce6224ef
authored
Aug 31, 2017
by
Pavel Vainerman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
(UActivator): рефакторинг процесса завершения.
Переделал обработку через libev. Убрал (пока) всё лишнее (создание дампа, защитный kill).
parent
30930362
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
103 additions
and
824 deletions
+103
-824
UniSetActivator.h
include/UniSetActivator.h
+12
-30
UniSetManager.h
include/UniSetManager.h
+13
-23
Configuration.cc
src/Core/Configuration.cc
+2
-2
UniSetActivator.cc
src/Core/UniSetActivator.cc
+71
-764
UniSetManager.cc
src/Core/UniSetManager.cc
+5
-5
No files found.
include/UniSetActivator.h
View file @
ce6224ef
...
...
@@ -25,9 +25,11 @@
#include <deque>
#include <memory>
#include <omniORB4/CORBA.h>
#include <ev++.h>
#include "UniSetTypes.h"
#include "UniSetObject.h"
#include "UniSetManager.h"
#include "EventLoopServer.h"
#include "OmniThreadCreator.h"
#include "UHttpRequestHandler.h"
#include "UHttpServer.h"
...
...
@@ -58,6 +60,7 @@ namespace uniset
*
*/
class
UniSetActivator
:
public
EventLoopServer
,
public
UniSetManager
#ifndef DISABLE_REST_API
,
public
uniset
::
UHttp
::
IHttpRequestRegistry
...
...
@@ -67,24 +70,16 @@ namespace uniset
static
UniSetActivatorPtr
Instance
();
std
::
shared_ptr
<
UniSetActivator
>
get_aptr
();
// ------------------------------------
virtual
~
UniSetActivator
();
virtual
void
run
(
bool
thread
);
virtual
void
stop
();
virtual
void
uaDestroy
(
int
signo
=
0
);
void
run
(
bool
async
);
void
stop
();
virtual
uniset
::
ObjectType
getType
()
override
{
return
uniset
::
ObjectType
(
"UniSetActivator"
);
}
typedef
sigc
::
signal
<
void
,
int
>
TerminateEvent_Signal
;
TerminateEvent_Signal
signal_terminate_event
();
bool
noUseGdbForStackTrace
()
const
;
const
std
::
string
getAbortScript
()
const
;
#ifndef DISABLE_REST_API
// Поддрежка REST API (IHttpRequestRegistry)
...
...
@@ -98,38 +93,25 @@ namespace uniset
virtual
void
work
();
CORBA
::
ORB_ptr
getORB
();
virtual
void
sysCommand
(
const
uniset
::
SystemMessage
*
sm
)
override
;
// уносим в protected, т.к. Activator должен быть только один..
UniSetActivator
();
static
std
::
shared_ptr
<
UniSetActivator
>
inst
;
private
:
friend
void
uniset
::
terminate_thread
();
friend
void
uniset
::
finished_thread
();
friend
std
::
shared_ptr
<
uniset
::
Configuration
>
uniset
::
uniset_init
(
int
argc
,
const
char
*
const
*
argv
,
const
std
::
string
&
xmlfile
);
static
void
terminated
(
int
signo
);
static
void
normalexit
();
static
void
normalterminate
();
static
void
set_signals
(
bool
ask
);
void
term
(
int
signo
);
void
init
();
static
void
evsignal
(
ev
::
sig
&
signal
,
int
signo
);
virtual
void
evprepare
()
override
;
virtual
void
evfinish
()
override
;
std
::
shared_ptr
<
OmniThreadCreator
<
UniSetActivator
>
>
orbthr
;
CORBA
::
ORB_var
orb
;
TerminateEvent_Signal
s_term
;
std
::
atomic_bool
omDestroy
;
pid_t
thid
=
{
0
};
// id orb потока
bool
_noUseGdbForStackTrace
=
{
false
};
std
::
string
abortScript
=
{
""
};
// скрипт вызываемый при прерывании программы (SIGSEGV,SIGABRT)
ev
::
sig
sigINT
;
ev
::
sig
sigTERM
;
ev
::
sig
sigABRT
;
ev
::
sig
sigQUIT
;
#ifndef DISABLE_REST_API
std
::
shared_ptr
<
uniset
::
UHttp
::
UHttpServer
>
httpserv
;
...
...
include/UniSetManager.h
View file @
ce6224ef
...
...
@@ -78,23 +78,6 @@ namespace uniset
virtual
bool
add
(
const
std
::
shared_ptr
<
UniSetObject
>&
obj
);
virtual
bool
remove
(
const
std
::
shared_ptr
<
UniSetObject
>&
obj
);
// --------------------------
/*! Получение доступа к подчиненному менеджеру по идентификатору
* \return shared_ptr<>, если объект не найден будет возвращен shared_ptr<> = nullptr
*/
const
std
::
shared_ptr
<
UniSetManager
>
itemM
(
const
uniset
::
ObjectId
id
);
/*! Получение доступа к подчиненному объекту по идентификатору
* \return shared_ptr<>, если объект не найден будет возвращен shared_ptr<> = nullptr
*/
const
std
::
shared_ptr
<
UniSetObject
>
itemO
(
const
uniset
::
ObjectId
id
);
// Функции для работы со списками подчиненных объектов
// ---------------
UniSetManagerList
::
const_iterator
beginMList
();
UniSetManagerList
::
const_iterator
endMList
();
ObjectsList
::
const_iterator
beginOList
();
ObjectsList
::
const_iterator
endOList
();
size_t
objectsCount
()
const
;
// количество подчиненных объектов
// ---------------
...
...
@@ -127,14 +110,14 @@ namespace uniset
//! \note Переопределяя не забывайте вызвать базовую
virtual
bool
deactivateObject
()
override
;
const
std
::
shared_ptr
<
UniSetObject
>
findObject
(
const
std
::
string
&
name
);
const
std
::
shared_ptr
<
UniSetManager
>
findManager
(
const
std
::
string
&
name
);
const
std
::
shared_ptr
<
UniSetObject
>
findObject
(
const
std
::
string
&
name
)
const
;
const
std
::
shared_ptr
<
UniSetManager
>
findManager
(
const
std
::
string
&
name
)
const
;
// рекурсивный поиск по всем объекам
const
std
::
shared_ptr
<
UniSetObject
>
deepFindObject
(
const
std
::
string
&
name
);
const
std
::
shared_ptr
<
UniSetObject
>
deepFindObject
(
const
std
::
string
&
name
)
const
;
// рекурсивное наполнение списка объектов
void
getAllObjectsList
(
std
::
vector
<
std
::
shared_ptr
<
UniSetObject
>
>&
vec
,
size_t
lim
=
1000
);
void
getAllObjectsList
(
std
::
vector
<
std
::
shared_ptr
<
UniSetObject
>
>&
vec
,
size_t
lim
=
1000
);
typedef
UniSetManagerList
::
iterator
MListIterator
;
...
...
@@ -144,14 +127,21 @@ namespace uniset
PortableServer
::
POA_var
poa
;
PortableServer
::
POAManager_var
pman
;
// Функции для работы со списками подчиненных объектов
// ---------------
UniSetManagerList
::
const_iterator
beginMList
();
UniSetManagerList
::
const_iterator
endMList
();
ObjectsList
::
const_iterator
beginOList
();
ObjectsList
::
const_iterator
endOList
();
private
:
int
sig
;
UniSetManagerList
mlist
;
ObjectsList
olist
;
uniset
::
uniset_rwmutex
olistMutex
;
uniset
::
uniset_rwmutex
mlistMutex
;
mutable
uniset
::
uniset_rwmutex
olistMutex
;
mutable
uniset
::
uniset_rwmutex
mlistMutex
;
};
// -------------------------------------------------------------------------
}
// end of uniset namespace
...
...
src/Core/Configuration.cc
View file @
ce6224ef
...
...
@@ -1452,8 +1452,8 @@ namespace uniset
return
uniset
::
uconf
;
}
atexit
(
UniSetActivator
::
normalexit
);
set_terminate
(
UniSetActivator
::
normalterminate
);
// ловушка для неизвестных исключений
//
atexit( UniSetActivator::normalexit );
//
set_terminate( UniSetActivator::normalterminate ); // ловушка для неизвестных исключений
string
confile
=
uniset
::
getArgParam
(
"--confile"
,
argc
,
argv
,
xmlfile
);
uniset
::
uconf
=
make_shared
<
Configuration
>
(
argc
,
argv
,
confile
);
...
...
src/Core/UniSetActivator.cc
View file @
ce6224ef
...
...
@@ -50,503 +50,24 @@
using
namespace
uniset
;
using
namespace
std
;
// ------------------------------------------------------------------------------------------
/*
Завершение работы организовано следующим образом:
-------------------------------------------------
Т.к. UniSetActivator в системе только один (singleton), он заказывает на себя
все сигналы связанные с завершением работы, а также устанавливает обработчики на штатный выход из программы (atexit)
и обработчик на выход по исключению (set_terminate).
В качестве обработчика сигналов регистрируется функция activator_terminate( int signo ).
При вызове run() (в функции work) создаётся "глобальный" поток g_term_thread, который
засыпает до события на condition переменной g_termevent.
Когда срабатывает обработчик сигнала, он выставляет флаг завершения (g_term=true) и вызывает
g_termevent.notify_one(); чтобы процесс завершения начал свою работу. (см. activator_terminate).
После этого начинается процесс завершения.
- orb shutdown
- uaDestroy()
- завершение CORBA-потока (если был создан) (функция work).
- orb destroy
Для защиты от "зависания" во время завершения, создаётся ещё один поток g_kill_thread, который ожидает завершения
в течение KILL_TIMEOUT и формирует сигнал SIGKILL если в течение этого времени не выставился флаг g_done = true;
Помимио этого в процессе завершения создаётся временный поток g_fini_thread,
который в течение TERMINATE_TIMEOUT секунд ждёт события 'g_finievent' (от процесса остановки котока для ORB).
После чего происходит "принудительное" отключение, обработчики сигналов восстанавливаются на умолчательные и процесс
завершается..
В случае, если для UniSetActivator был создан отдельный поток ( run(true) ) при завершении работы программы
срабатывает обработчик UniSetActivator::normalexit или UniSetActivator::normalterminate, которые
делают тоже самое. Будят процесс завершения.. и дожидаются завершения его работы.
// Обработка SIGSEGV
Для обработки SIGSEGV выделен отдельный обработчик (activator_terminate_with_calltrace),
который выводит stack trace и завершает работу.
Если для ulog включён SYSTEM, то trace выводится в него для возможности (если получиться)
увидеть его удалённо через logserver (если он запушен).
Если не включён, то выводиться в cerr.
Сам обработчик только выводит trace и завершает работу, восстановив обработчик SIGSEGV по умолчанию,
без какой-либо специальной обработки завершения.
Помимо этого, вывод stack trace сделан и для сигнала SIGABRT
*/
// ------------------------------------------------------------------------------------------
static
std
::
shared_ptr
<
UniSetActivator
>
g_act
;
static
std
::
atomic_bool
g_finished
=
ATOMIC_VAR_INIT
(
0
);
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_work_stopped
=
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_termmutex
;
static
std
::
condition_variable
g_termevent
;
static
std
::
mutex
g_finimutex
;
static
std
::
condition_variable
g_finievent
;
static
std
::
mutex
g_donemutex
;
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_fini_thread
;
static
std
::
shared_ptr
<
std
::
thread
>
g_kill_thread
;
static
const
int
TERMINATE_TIMEOUT_SEC
=
3
;
// время отведенное на завершение процесса [сек]
static
const
int
THREAD_TERMINATE_PAUSE
=
50
;
// [мсек] пауза при завершении потока (см. work())
static
const
int
KILL_TIMEOUT_SEC
=
8
;
static
pid_t
g_stacktrace_proc_pid
=
0
;
// pid процесса делающего stack trace (для защиты от зависания)
// ------------------------------------------------------------------------------------------
// Чтобы не выделять память во время "вылета",
// выделим необходимое для stacktrace зараннее
// ----------
#define FUNCNAMESIZE 256
#define MAXFRAMES 64
// выделение специального стека заранее
// +60 - это на всякие переменные при обработке stack trace и т.п.
static
char
g_stack_body
[(
MAXFRAMES
+
60
)
*
FUNCNAMESIZE
];
//static char trace_buf[10000];
static
stack_t
g_sigseg_stack
;
static
void
on_stacktrace_timeout
();
// поток для защиты от зависания "процесса создания stack trace"
// ------------------------------------------------------------------------------------------
// код функции printStackTrace взят с https://oroboro.com/stack-trace-on-crash/
// будет работать только под LINUX (т.к. используется backtrace)
// Как альтернативу, можно применить libunwind
// ------------------------------------------------------------------------------------------
// Выводим используя ulog() чтобы можно было удалённо увидеть через LogServer
// (хотя конечно это как повезёт и зависит от того где собственно произошла ошибка)
// ------------------------------------------------------------------------------------------
#define TRACELOG ( to_cerr ? cerr : log->system(false) )
static
inline
void
printStackTrace
()
{
auto
log
=
ulog
();
// если логи отключены, то и выводить не будем
bool
to_cerr
=
(
!
log
||
!
log
->
is_system
()
);
// первый лог выводим с датой, а дальше уже просто
(
to_cerr
?
cerr
:
log
->
system
()
)
<<
"stack trace:
\n
"
;
TRACELOG
<<
"-----------------------------------------"
<<
endl
;
void
*
addrlist
[
MAXFRAMES
];
// retrieve current stack addresses
unsigned
int
addrlen
=
backtrace
(
addrlist
,
MAXFRAMES
);
if
(
addrlen
==
0
)
{
log
->
system
()
<<
"...empty stack..
\n
"
;
return
;
}
// resolve addresses into strings containing "filename(function+address)",
// Actually it will be ## program address function + offset
// this array must be free()-ed
char
**
symbollist
=
backtrace_symbols
(
addrlist
,
addrlen
);
TRACELOG
<<
std
::
left
;
// iterate over the returned symbol lines. skip the first, it is the
// address of this function.
for
(
unsigned
int
i
=
4
;
i
<
addrlen
;
i
++
)
{
Dl_info
dl
;
if
(
!
dladdr
(
addrlist
[
i
],
&
dl
))
break
;
const
char
*
sym
=
dl
.
dli_sname
;
int
status
=
0
;
char
*
ret
=
abi
::
__cxa_demangle
(
sym
,
NULL
,
0
,
&
status
);
if
(
status
==
0
&&
ret
)
sym
=
ret
;
if
(
dl
.
dli_fname
&&
sym
)
{
TRACELOG
<<
setw
(
30
)
<<
symbollist
[
i
]
<<
" ( "
<<
setw
(
40
)
<<
dl
.
dli_fname
<<
" ): "
<<
sym
<<
endl
<<
flush
;
}
else
{
TRACELOG
<<
setw
(
30
)
<<
symbollist
[
i
]
<<
endl
<<
flush
;
}
if
(
ret
)
std
::
free
(
ret
);
}
std
::
free
(
symbollist
);
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
];
ssize_t
ind
=
readlink
(
"/proc/self/exe"
,
name_buf
,
511
);
if
(
ind
<
0
)
{
perror
(
"Can't readlink..."
);
return
false
;
}
name_buf
[
ind
]
=
0
;
TRACELOG
<<
"stack trace: for "
<<
name_buf
<<
" pid="
<<
pid_buf
<<
endl
;
int
child_pid
=
fork
();
if
(
child_pid
==
-
1
)
{
perror
(
"Can't fork..."
);
return
false
;
}
if
(
child_pid
==
0
)
// CHILD
{
msleep
(
300
);
// пауза чтобы родитель успел подготовиться..
dup2
(
2
,
1
);
// redirect output to stderr
if
(
g_act
&&
!
g_act
->
getAbortScript
().
empty
()
)
{
TRACELOG
<<
"run script: "
<<
g_act
->
getAbortScript
()
<<
" for stack trace: proc "
<<
name_buf
<<
" pid="
<<
pid_buf
<<
endl
;
execlp
(
g_act
->
getAbortScript
().
c_str
(),
g_act
->
getAbortScript
().
c_str
(),
name_buf
,
pid_buf
,
NULL
);
}
else
{
TRACELOG
<<
"direct run gdb for stack trace for pid="
<<
pid_buf
<<
" name="
<<
name_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
// PARENT
{
if
(
g_act
&&
!
g_act
->
getAbortScript
().
empty
()
)
{
TRACELOG
<<
"stack trace: run script "
<<
g_act
->
getAbortScript
()
<<
endl
;
}
g_stacktrace_proc_pid
=
child_pid
;
g_trace_done
=
false
;
std
::
thread
t
(
on_stacktrace_timeout
);
// запускаем поток "защищающий" от зависания процесса создания stack trace
waitpid
(
child_pid
,
NULL
,
0
);
g_trace_done
=
true
;
g_trace_doneevent
.
notify_all
();
t
.
join
();
}
TRACELOG
<<
"-----------------------------------------"
<<
endl
<<
flush
;
return
true
;
}
// ------------------------------------------------------------------------------------------
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
);
g_trace_doneevent
.
wait_for
(
lk
,
std
::
chrono
::
milliseconds
(
KILL_TIMEOUT_SEC
*
1000
),
[]()
{
return
(
g_trace_done
==
true
);
}
);
if
(
!
g_trace_done
)
{
ulogsys
<<
"****** STACK TRACE TIMEOUT.. (kill process) *******"
<<
endl
<<
flush
;
kill
(
g_stacktrace_proc_pid
,
SIGKILL
);
}
else
ulogsys
<<
"****** STACK TRACE guard thread finish ******"
<<
endl
<<
flush
;
}
// ------------------------------------------------------------------------------------------
static
void
start_terminate_process
()
{
// посылаем сигнал потоку завершения, чтобы проснулся и начал заверешение
{
std
::
unique_lock
<
std
::
mutex
>
lk
(
g_termmutex
);
if
(
g_term
)
return
;
g_term
=
true
;
}
g_termevent
.
notify_all
();
}
// ------------------------------------------------------------------------------------------
static
void
wait_done
()
{
std
::
unique_lock
<
std
::
mutex
>
lk
(
g_donemutex
);
while
(
!
g_done
)
g_doneevent
.
wait
(
lk
,
[]()
{
return
(
g_done
==
true
);
}
);
}
// ------------------------------------------------------------------------------------------
static
void
activator_terminate
(
int
signo
)
{
if
(
g_term
)
return
;
g_signo
=
signo
;
if
(
signo
==
SIGABRT
)
{
if
(
g_act
&&
!
g_act
->
noUseGdbForStackTrace
()
)
{
if
(
!
gdb_print_trace
()
)
printStackTrace
();
// пробуем сами..
}
else
printStackTrace
();
// exit(EXIT_FAILURE);
// return;
}
// else
// exit(EXIT_SUCCESS);
start_terminate_process
();
}
// ------------------------------------------------------------------------------------------
static
void
activator_terminate_with_calltrace
(
int
signo
)
{
if
(
g_act
&&
!
g_act
->
noUseGdbForStackTrace
()
)
{
if
(
!
gdb_print_trace
()
)
printStackTrace
();
// пробуем сами..
}
else
printStackTrace
();
// т.к. это SIGSEGV, то просто вылетаем по умолчанию..
signal
(
signo
,
SIG_DFL
);
raise
(
signo
);
}
// ------------------------------------------------------------------------------------------
void
finished_thread
()
{
ulogsys
<<
"****** WAIT FINISH START **** "
<<
endl
<<
flush
;
std
::
unique_lock
<
std
::
mutex
>
lk
(
g_finimutex
);
if
(
g_finished
)
return
;
g_finished
=
true
;
std
::
unique_lock
<
std
::
mutex
>
lkw
(
g_workmutex
);
g_finievent
.
wait_for
(
lkw
,
std
::
chrono
::
milliseconds
(
TERMINATE_TIMEOUT_SEC
*
1000
),
[]()
{
return
(
g_work_stopped
==
true
);
}
);
ulogsys
<<
"****** WAIT FINISH END("
<<
g_work_stopped
<<
") ****"
<<
endl
<<
flush
;
}
// ------------------------------------------------------------------------------------------
void
on_finish_timeout
()
{
std
::
unique_lock
<
std
::
mutex
>
lk
(
g_donemutex
);
if
(
g_done
)
return
;
g_doneevent
.
wait_for
(
lk
,
std
::
chrono
::
milliseconds
(
KILL_TIMEOUT_SEC
*
1000
),
[]()
{
return
(
g_done
==
true
);
}
);
if
(
!
g_done
)
{
ulogsys
<<
"(KILL THREAD): WAIT TIMEOUT..KILL *******"
<<
endl
<<
flush
;
raise
(
SIGKILL
);
}
ulogsys
<<
"(KILL THREAD): ..bye.."
<<
endl
;
}
// ------------------------------------------------------------------------------------------
namespace
uniset
{
void
terminate_thread
()
{
ulogsys
<<
"****** TERMINATE THREAD: STARTED *******"
<<
endl
<<
flush
;
{
std
::
unique_lock
<
std
::
mutex
>
locker
(
g_termmutex
);
g_term
=
false
;
while
(
!
g_term
)
g_termevent
.
wait
(
locker
);
// g_termmutex надо отпустить, т.к. он будет проверяться в ~UniSetActvator
}
ulogsys
<<
"****** TERMINATE THREAD: event signo="
<<
g_signo
<<
endl
<<
flush
;
{
std
::
unique_lock
<
std
::
mutex
>
locker
(
g_finimutex
);
if
(
g_finished
)
return
;
}
{
std
::
unique_lock
<
std
::
mutex
>
lk
(
g_donemutex
);
g_done
=
false
;
g_kill_thread
=
make_shared
<
std
::
thread
>
(
on_finish_timeout
);
}
if
(
g_act
)
{
{
std
::
unique_lock
<
std
::
mutex
>
lk
(
g_finimutex
);
if
(
g_finished
)
{
ulogsys
<<
"...FINISHED ALREADY STARTED..."
<<
endl
<<
flush
;
return
;
}
g_fini_thread
=
make_shared
<
std
::
thread
>
(
finished_thread
);
}
ulogsys
<<
"(TERMINATE THREAD): call terminated.."
<<
endl
<<
flush
;
g_act
->
terminated
(
g_signo
);
#if 0
try
{
ulogsys << "TERMINATE THREAD: orb shutdown.." << endl;
if( g_act->orb )
g_act->orb->shutdown(true);
ulogsys << "TERMINATE THREAD: orb shutdown ok.." << endl;
}
catch( const omniORB::fatalException& fe )
{
ulogsys << "(TERMINATE THREAD): : omniORB::fatalException:" << endl;
ulogsys << "(TERMINATE THREAD): file: " << fe.file() << endl;
ulogsys << "(TERMINATE THREAD): line: " << fe.line() << endl;
ulogsys << "(TERMINATE THREAD): mesg: " << fe.errmsg() << endl;
}
catch( const std::exception& ex )
{
ulogsys << "(TERMINATE THREAD): " << ex.what() << endl;
}
#endif
if
(
g_fini_thread
&&
g_fini_thread
->
joinable
()
)
g_fini_thread
->
join
();
ulogsys
<<
"(TERMINATE THREAD): FINISHED OK.."
<<
endl
<<
flush
;
if
(
g_act
&&
g_act
->
orb
)
{
try
{
ulogsys
<<
"(TERMINATE THREAD): destroy.."
<<
endl
;
g_act
->
orb
->
destroy
();
ulogsys
<<
"(TERMINATE THREAD): destroy ok.."
<<
endl
;
}
catch
(
const
omniORB
::
fatalException
&
fe
)
{
ulogsys
<<
"(TERMINATE THREAD): : omniORB::fatalException:"
<<
endl
;
ulogsys
<<
"(TERMINATE THREAD): file: "
<<
fe
.
file
()
<<
endl
;
ulogsys
<<
"(TERMINATE THREAD): line: "
<<
fe
.
line
()
<<
endl
;
ulogsys
<<
"(TERMINATE THREAD): mesg: "
<<
fe
.
errmsg
()
<<
endl
;
}
catch
(
const
std
::
exception
&
ex
)
{
ulogsys
<<
"(TERMINATE THREAD): "
<<
ex
.
what
()
<<
endl
;
}
}
// g_act = nullptr;
UniSetActivator
::
set_signals
(
false
);
}
{
std
::
unique_lock
<
std
::
mutex
>
lk
(
g_donemutex
);
g_done
=
true
;
}
g_doneevent
.
notify_all
();
g_kill_thread
->
join
();
ulogsys
<<
"(TERMINATE THREAD): ..bye.."
<<
endl
;
}
}
// ---------------------------------------------------------------------------
UniSetActivatorPtr
UniSetActivator
::
inst
;
// ---------------------------------------------------------------------------
UniSetActivatorPtr
UniSetActivator
::
Instance
()
{
if
(
inst
==
nullptr
)
{
inst
=
shared_ptr
<
UniSetActivator
>
(
new
UniSetActivator
()
);
g_act
=
inst
;
}
return
inst
;
}
// ---------------------------------------------------------------------------
std
::
shared_ptr
<
UniSetActivator
>
UniSetActivator
::
get_aptr
()
{
return
std
::
dynamic_pointer_cast
<
UniSetActivator
>
(
get_ptr
());
}
// ---------------------------------------------------------------------------
UniSetActivator
::
UniSetActivator
()
:
UniSetManager
(
uniset
::
DefaultObjectId
),
omDestroy
(
false
)
UniSetManager
(
uniset
::
DefaultObjectId
)
{
// thread(false); // отключаем поток (раз не задан id)
UniSetActivator
::
init
();
}
// ------------------------------------------------------------------------------------------
void
UniSetActivator
::
init
()
{
...
...
@@ -555,10 +76,6 @@ void UniSetActivator::init()
auto
conf
=
uniset_conf
();
_noUseGdbForStackTrace
=
(
findArgParam
(
"--uniset-no-use-gdb-for-stacktrace"
,
conf
->
getArgc
(),
conf
->
getArgv
())
!=
-
1
);
abortScript
=
conf
->
getArgParam
(
"--uniset-abort-script"
,
""
);
#ifndef DISABLE_REST_API
if
(
findArgParam
(
"--activator-run-httpserver"
,
conf
->
getArgc
(),
conf
->
getArgv
())
!=
-
1
)
...
...
@@ -580,76 +97,27 @@ void UniSetActivator::init()
poa
=
root_poa
->
create_POA
(
"my poa"
,
pman
,
pl
);
if
(
CORBA
::
is_nil
(
poa
)
)
{
ucrit
<<
myname
<<
"(init): init poa failed!!!"
<<
endl
;
std
::
terminate
();
}
// Чтобы подключиться к функциям завершения как можно раньше (раньше создания объектов)
// этот код перенесён в Configuration::uniset_init (в надежде, что uniset_init всегда вызывается одной из первых).
// atexit( UniSetActivator::normalexit );
// set_terminate( UniSetActivator::normalterminate ); // ловушка для неизвестных исключений
sigTERM
.
set
(
loop
);
sigINT
.
set
(
loop
);
sigABRT
.
set
(
loop
);
sigQUIT
.
set
(
loop
);
sigINT
.
set
<&
UniSetActivator
::
evsignal
>
();
sigTERM
.
set
<&
UniSetActivator
::
evsignal
>
();
sigABRT
.
set
<&
UniSetActivator
::
evsignal
>
();
sigQUIT
.
set
<&
UniSetActivator
::
evsignal
>
();
}
// ------------------------------------------------------------------------------------------
UniSetActivator
::~
UniSetActivator
()
{
}
// ------------------------------------------------------------------------------------------
void
UniSetActivator
::
uaDestroy
(
int
signo
)
{
if
(
omDestroy
||
!
g_act
)
return
;
omDestroy
=
true
;
ulogsys
<<
myname
<<
"(uaDestroy): begin..."
<<
endl
;
ulogsys
<<
myname
<<
"(uaDestroy): terminate... "
<<
endl
;
term
(
signo
);
ulogsys
<<
myname
<<
"(uaDestroy): terminate ok. "
<<
endl
;
try
{
if
(
active
)
stop
();
}
catch
(
const
omniORB
::
fatalException
&
fe
)
{
ucrit
<<
myname
<<
"(uaDestroy): : поймали omniORB::fatalException:"
<<
endl
;
ucrit
<<
myname
<<
"(uaDestroy): file: "
<<
fe
.
file
()
<<
endl
;
ucrit
<<
myname
<<
"(uaDestroy): line: "
<<
fe
.
line
()
<<
endl
;
ucrit
<<
myname
<<
"(uaDestroy): mesg: "
<<
fe
.
errmsg
()
<<
endl
;
}
catch
(...)
{
ulogsys
<<
myname
<<
"(uaDestroy): orb shutdown: catch... "
<<
endl
;
}
ulogsys
<<
myname
<<
"(uaDestroy): pman deactivate... "
<<
endl
;
pman
->
deactivate
(
false
,
true
);
ulogsys
<<
myname
<<
"(uaDestroy): pman deactivate ok. "
<<
endl
;
try
{
ulogsys
<<
myname
<<
"(uaDestroy): shutdown orb... "
<<
endl
;
if
(
orb
)
orb
->
shutdown
(
true
);
ulogsys
<<
myname
<<
"(uaDestroy): shutdown ok."
<<
endl
;
}
catch
(
const
omniORB
::
fatalException
&
fe
)
{
ucrit
<<
myname
<<
"(uaDestroy): : поймали omniORB::fatalException:"
<<
endl
;
ucrit
<<
myname
<<
"(uaDestroy): file: "
<<
fe
.
file
()
<<
endl
;
ucrit
<<
myname
<<
"(uaDestroy): line: "
<<
fe
.
line
()
<<
endl
;
ucrit
<<
myname
<<
"(uaDestroy): mesg: "
<<
fe
.
errmsg
()
<<
endl
;
}
catch
(
const
std
::
exception
&
ex
)
{
ucrit
<<
myname
<<
"(uaDestroy): "
<<
ex
.
what
()
<<
endl
;
}
ulogsys
<<
myname
<<
"(uaDestroy): begin..."
<<
endl
;
}
// ------------------------------------------------------------------------------------------
/*!
* Если thread=true то функция создает отдельный поток для обработки приходящих сообщений.
...
...
@@ -663,7 +131,9 @@ void UniSetActivator::run( bool thread )
{
ulogsys
<<
myname
<<
"(run): создаю менеджер "
<<
endl
;
UniSetManager
::
initPOA
(
get_aptr
()
);
auto
aptr
=
std
::
static_pointer_cast
<
UniSetActivator
>
(
get_ptr
());
UniSetManager
::
initPOA
(
aptr
);
if
(
getId
()
==
uniset
::
DefaultObjectId
)
offThread
();
// отключение потока обработки сообщений, раз не задан ObjectId
...
...
@@ -675,7 +145,8 @@ void UniSetActivator::run( bool thread )
pman
->
activate
();
msleep
(
50
);
set_signals
(
true
);
if
(
!
thread
)
async_evrun
();
#ifndef DISABLE_REST_API
...
...
@@ -698,13 +169,14 @@ void UniSetActivator::run( bool thread )
if
(
thread
)
{
uinfo
<<
myname
<<
"(run): запускаемся с созданием отдельного потока... "
<<
endl
;
orbthr
=
make_shared
<
OmniThreadCreator
<
UniSetActivator
>
>
(
get_aptr
()
,
&
UniSetActivator
::
work
);
orbthr
=
make_shared
<
OmniThreadCreator
<
UniSetActivator
>
>
(
aptr
,
&
UniSetActivator
::
work
);
orbthr
->
start
();
}
else
{
uinfo
<<
myname
<<
"(run): запускаемся без создания отдельного потока... "
<<
endl
;
work
();
evstop
();
}
}
// ------------------------------------------------------------------------------------------
...
...
@@ -736,22 +208,65 @@ void UniSetActivator::stop()
httpserv
->
stop
();
#endif
ulogsys
<<
myname
<<
"(stop): pman deactivate... "
<<
endl
;
pman
->
deactivate
(
false
,
true
);
ulogsys
<<
myname
<<
"(stop): pman deactivate ok. "
<<
endl
;
try
{
ulogsys
<<
myname
<<
"(stop): shutdown orb... "
<<
endl
;
if
(
orb
)
orb
->
shutdown
(
true
);
ulogsys
<<
myname
<<
"(stop): shutdown ok."
<<
endl
;
}
catch
(
const
omniORB
::
fatalException
&
fe
)
{
ucrit
<<
myname
<<
"(stop): : поймали omniORB::fatalException:"
<<
endl
;
ucrit
<<
myname
<<
"(stop): file: "
<<
fe
.
file
()
<<
endl
;
ucrit
<<
myname
<<
"(stop): line: "
<<
fe
.
line
()
<<
endl
;
ucrit
<<
myname
<<
"(stop): mesg: "
<<
fe
.
errmsg
()
<<
endl
;
}
catch
(
const
std
::
exception
&
ex
)
{
ucrit
<<
myname
<<
"(stop): "
<<
ex
.
what
()
<<
endl
;
}
if
(
orbthr
)
orbthr
->
join
();
}
// ------------------------------------------------------------------------------------------
void
UniSetActivator
::
evsignal
(
ev
::
sig
&
signal
,
int
signo
)
{
auto
act
=
UniSetActivator
::
Instance
();
act
->
stop
();
}
// ------------------------------------------------------------------------------------------
void
UniSetActivator
::
evprepare
()
{
sigINT
.
start
(
SIGINT
);
sigTERM
.
start
(
SIGTERM
);
sigABRT
.
start
(
SIGABRT
);
sigQUIT
.
start
(
SIGQUIT
);
}
// ------------------------------------------------------------------------------------------
void
UniSetActivator
::
evfinish
()
{
sigINT
.
stop
();
sigTERM
.
stop
();
sigABRT
.
stop
();
sigQUIT
.
stop
();
}
// ------------------------------------------------------------------------------------------
void
UniSetActivator
::
work
()
{
ulogsys
<<
myname
<<
"(work): запускаем orb на обработку запросов..."
<<
endl
;
try
{
if
(
orbthr
)
thid
=
orbthr
->
getTID
();
else
thid
=
getpid
();
g_term_thread
=
make_shared
<
std
::
thread
>
(
terminate_thread
);
omniORB
::
setMainThread
();
orb
->
run
();
}
...
...
@@ -776,123 +291,6 @@ void UniSetActivator::work()
}
ulogsys
<<
myname
<<
"(work): orb thread stopped!"
<<
endl
<<
flush
;
{
std
::
unique_lock
<
std
::
mutex
>
lkw
(
g_workmutex
);
g_work_stopped
=
true
;
}
g_finievent
.
notify_one
();
if
(
orbthr
)
{
// почему-то без этой паузы при завершении возникает "double free or corruption"
// и вообще какой-то race между завершением штатным и нашим
// видимо потому-что обычно activator запускается в main()
// и как только этот поток прерывается идёт завершение работы
// а мы и так уже завершаемся.. и получается какой-то race..
msleep
(
THREAD_TERMINATE_PAUSE
);
wait_done
();
}
}
// ------------------------------------------------------------------------------------------
CORBA
::
ORB_ptr
UniSetActivator
::
getORB
()
{
return
orb
;
}
// ------------------------------------------------------------------------------------------
void
UniSetActivator
::
sysCommand
(
const
uniset
::
SystemMessage
*
sm
)
{
switch
(
sm
->
command
)
{
case
SystemMessage
:
:
LogRotate
:
{
ulogsys
<<
myname
<<
"(sysCommand): logRotate"
<<
endl
;
auto
ul
=
ulog
();
if
(
!
ul
)
break
;
// переоткрываем логи
string
fname
=
ul
->
getLogFile
();
if
(
fname
.
empty
()
)
{
ul
->
logFile
(
fname
.
c_str
(),
true
);
ulogany
<<
myname
<<
"(sysCommand): ***************** ulog LOG ROTATE *****************"
<<
endl
;
}
}
break
;
}
}
// -------------------------------------------------------------------------
void
UniSetActivator
::
set_signals
(
bool
ask
)
{
struct
sigaction
act
;
// = { { 0 } };
struct
sigaction
oact
;
// = { { 0 } };
memset
(
&
act
,
0
,
sizeof
(
act
));
memset
(
&
act
,
0
,
sizeof
(
oact
));
sigemptyset
(
&
act
.
sa_mask
);
sigemptyset
(
&
oact
.
sa_mask
);
// добавляем сигналы, которые будут игнорироваться
// при обработке сигнала
sigaddset
(
&
act
.
sa_mask
,
SIGINT
);
sigaddset
(
&
act
.
sa_mask
,
SIGTERM
);
sigaddset
(
&
act
.
sa_mask
,
SIGABRT
);
sigaddset
(
&
act
.
sa_mask
,
SIGQUIT
);
// sigaddset(&act.sa_mask, SIGALRM);
// act.sa_flags = 0;
// act.sa_flags |= SA_RESTART;
// act.sa_flags |= SA_RESETHAND;
if
(
ask
)
act
.
sa_handler
=
activator_terminate
;
// terminated;
else
act
.
sa_handler
=
SIG_DFL
;
sigaction
(
SIGINT
,
&
act
,
&
oact
);
sigaction
(
SIGTERM
,
&
act
,
&
oact
);
sigaction
(
SIGABRT
,
&
act
,
&
oact
);
sigaction
(
SIGQUIT
,
&
act
,
&
oact
);
// SIGSEGV отдельно
sigemptyset
(
&
act
.
sa_mask
);
sigaddset
(
&
act
.
sa_mask
,
SIGSEGV
);
act
.
sa_flags
=
0
;
// act.sa_flags |= SA_RESTART;
act
.
sa_flags
|=
SA_RESETHAND
;
#if 1
g_sigseg_stack
.
ss_sp
=
g_stack_body
;
g_sigseg_stack
.
ss_flags
=
SS_ONSTACK
;
g_sigseg_stack
.
ss_size
=
sizeof
(
g_stack_body
);
assert
(
!
sigaltstack
(
&
g_sigseg_stack
,
nullptr
));
act
.
sa_flags
|=
SA_ONSTACK
;
#endif
if
(
ask
)
act
.
sa_handler
=
activator_terminate_with_calltrace
;
else
act
.
sa_handler
=
SIG_DFL
;
sigaction
(
SIGSEGV
,
&
act
,
&
oact
);
}
// ------------------------------------------------------------------------------------------
UniSetActivator
::
TerminateEvent_Signal
UniSetActivator
::
signal_terminate_event
()
{
return
s_term
;
}
// ------------------------------------------------------------------------------------------
bool
UniSetActivator
::
noUseGdbForStackTrace
()
const
{
return
_noUseGdbForStackTrace
;
}
// ------------------------------------------------------------------------------------------
const
string
UniSetActivator
::
getAbortScript
()
const
{
return
abortScript
;
}
// ------------------------------------------------------------------------------------------
#ifndef DISABLE_REST_API
...
...
@@ -966,96 +364,5 @@ Poco::JSON::Object::Ptr UniSetActivator::httpRequestByName( const string& name,
// ------------------------------------------------------------------------------------------
#endif // #ifndef DISABLE_REST_API
// ------------------------------------------------------------------------------------------
void
UniSetActivator
::
terminated
(
int
signo
)
{
if
(
!
g_act
)
return
;
ulogsys
<<
"(terminated): start.."
<<
endl
;
try
{
g_act
->
uaDestroy
(
signo
);
ulogsys
<<
"(terminated): uaDestroy ok.."
<<
endl
;
}
catch
(
const
omniORB
::
fatalException
&
fe
)
{
ulogsys
<<
"(terminated): : поймали omniORB::fatalException:"
<<
endl
;
ulogsys
<<
"(terminated): file: "
<<
fe
.
file
()
<<
endl
;
ulogsys
<<
"(terminated): line: "
<<
fe
.
line
()
<<
endl
;
ulogsys
<<
"(terminated): mesg: "
<<
fe
.
errmsg
()
<<
endl
;
}
catch
(
const
std
::
exception
&
ex
)
{
ulogsys
<<
"(terminated): "
<<
ex
.
what
()
<<
endl
;
}
g_term
=
true
;
ulogsys
<<
"terminated ok.."
<<
endl
;
}
// ------------------------------------------------------------------------------------------
void
UniSetActivator
::
normalexit
()
{
if
(
!
g_act
)
return
;
ulogsys
<<
g_act
->
getName
()
<<
"(exit): ..begin..."
<<
endl
<<
flush
;
start_terminate_process
();
ulogsys
<<
"(exit): wait done.."
<<
endl
<<
flush
;
#if 1
if
(
g_term_thread
&&
g_term_thread
->
joinable
()
)
g_term_thread
->
join
();
#else
if
(
g_doneevent
)
{
std
::
unique_lock
<
std
::
mutex
>
locker
(
g_donemutex
);
while
(
!
g_done
)
g_doneevent
.
wait
(
locker
);
}
#endif
ulogsys
<<
"(exit): wait done OK (good bye)"
<<
endl
<<
flush
;
}
// ------------------------------------------------------------------------------------------
void
UniSetActivator
::
normalterminate
()
{
if
(
!
g_act
)
return
;
ulogsys
<<
g_act
->
getName
()
<<
"(default terminate): ..begin..."
<<
endl
<<
flush
;
normalexit
();
}
// ------------------------------------------------------------------------------------------
void
UniSetActivator
::
term
(
int
signo
)
{
ulogsys
<<
myname
<<
"(term): TERM"
<<
endl
;
{
std
::
unique_lock
<
std
::
mutex
>
locker
(
g_termmutex
);
if
(
g_term
)
return
;
}
try
{
ulogsys
<<
myname
<<
"(term): вызываем sigterm()"
<<
endl
;
sigterm
(
signo
);
s_term
.
emit
(
signo
);
ulogsys
<<
myname
<<
"(term): sigterm() ok."
<<
endl
;
}
catch
(
const
uniset
::
Exception
&
ex
)
{
ucrit
<<
myname
<<
"(term): "
<<
ex
<<
endl
;
}
catch
(...)
{}
ulogsys
<<
myname
<<
"(term): END TERM"
<<
endl
;
}
}
// end of namespace uniset
// ------------------------------------------------------------------------------------------
src/Core/UniSetManager.cc
View file @
ce6224ef
...
...
@@ -465,7 +465,7 @@ bool UniSetManager::deactivateObject()
return
true
;
}
// ------------------------------------------------------------------------------------------
const
std
::
shared_ptr
<
UniSetObject
>
UniSetManager
::
findObject
(
const
string
&
name
)
const
std
::
shared_ptr
<
UniSetObject
>
UniSetManager
::
findObject
(
const
string
&
name
)
const
{
uniset_rwmutex_rlock
lock
(
olistMutex
);
...
...
@@ -478,7 +478,7 @@ const std::shared_ptr<UniSetObject> UniSetManager::findObject( const string& nam
return
nullptr
;
}
// ------------------------------------------------------------------------------------------
const
std
::
shared_ptr
<
UniSetManager
>
UniSetManager
::
findManager
(
const
string
&
name
)
const
std
::
shared_ptr
<
UniSetManager
>
UniSetManager
::
findManager
(
const
string
&
name
)
const
{
uniset_rwmutex_rlock
lock
(
mlistMutex
);
...
...
@@ -491,7 +491,7 @@ const std::shared_ptr<UniSetManager> UniSetManager::findManager( const string& n
return
nullptr
;
}
// ------------------------------------------------------------------------------------------
const
std
::
shared_ptr
<
UniSetObject
>
UniSetManager
::
deepFindObject
(
const
string
&
name
)
const
std
::
shared_ptr
<
UniSetObject
>
UniSetManager
::
deepFindObject
(
const
string
&
name
)
const
{
{
auto
obj
=
findObject
(
name
);
...
...
@@ -617,7 +617,7 @@ bool UniSetManager::removeManager( const std::shared_ptr<UniSetManager>& child )
}
// ------------------------------------------------------------------------------------------
#if 0
const std::shared_ptr<UniSetManager> UniSetManager::itemM( const ObjectId id )
{
...
...
@@ -652,7 +652,7 @@ const std::shared_ptr<UniSetObject> UniSetManager::itemO( const ObjectId id )
return nullptr; // std::shared_ptr<UniSetObject>();
}
#endif
// ------------------------------------------------------------------------------------------
int
UniSetManager
::
getObjectsInfo
(
const
std
::
shared_ptr
<
UniSetManager
>&
mngr
,
SimpleInfoSeq
*
seq
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment