summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/appMain/life_cycle.cc11
-rw-r--r--src/appMain/main.cc6
-rw-r--r--src/components/utils/include/utils/signals.h5
-rw-r--r--src/components/utils/src/signals_linux.cc63
-rw-r--r--src/components/utils/src/threads/posix_thread.cc17
5 files changed, 55 insertions, 47 deletions
diff --git a/src/appMain/life_cycle.cc b/src/appMain/life_cycle.cc
index 990251e990..8a106105ad 100644
--- a/src/appMain/life_cycle.cc
+++ b/src/appMain/life_cycle.cc
@@ -1,4 +1,4 @@
-/*
+e*
* Copyright (c) 2014, Ford Motor Company
* All rights reserved.
*
@@ -387,14 +387,9 @@ namespace {
void LifeCycle::Run() {
LOG4CXX_AUTO_TRACE(logger_);
- // First, register signal handlers
- if (!::utils::SubscribeToInterruptSignal(&sig_handler) ||
- !::utils::SubscribeToTerminateSignal(&sig_handler) ||
- !::utils::SubscribeToFaultSignal(&sig_handler)) {
- LOG4CXX_FATAL(logger_, "Subscribe to system signals error");
+ if (!utils::WaitTerminationSignals(&sig_handler)) {
+ LOG4CXX_WARN(logger_, "Fail to catch system signal!");
}
- // Now wait for any signal
- pause();
}
void LifeCycle::StopComponents() {
diff --git a/src/appMain/main.cc b/src/appMain/main.cc
index 9e1a49e2d4..8ec46180a7 100644
--- a/src/appMain/main.cc
+++ b/src/appMain/main.cc
@@ -125,6 +125,12 @@ int32_t main(int32_t argc, char** argv) {
profile::Profile::instance()->config_file_name("smartDeviceLink.ini");
}
+ // Unsibscribe once for all threads
+ if ( utils::UnsibscribeFromTermination() ) {
+ // Can't use internal logger here
+ exit(EXIT_FAILURE);
+ }
+
// Logger initialization
INIT_LOGGER("log4cxx.properties");
diff --git a/src/components/utils/include/utils/signals.h b/src/components/utils/include/utils/signals.h
index 7660a53cc3..b8b71b95e3 100644
--- a/src/components/utils/include/utils/signals.h
+++ b/src/components/utils/include/utils/signals.h
@@ -41,9 +41,8 @@ typedef void (*sighandler_t) (int);
namespace utils {
-bool SubscribeToInterruptSignal(sighandler_t func);
-bool SubscribeToTerminateSignal(sighandler_t func);
-bool SubscribeToFaultSignal(sighandler_t func);
+bool UnsibscribeFromTermination();
+bool WaitTerminationSignals(sighandler_t sig_handler);
} // namespace utils
diff --git a/src/components/utils/src/signals_linux.cc b/src/components/utils/src/signals_linux.cc
index 3f65e905b8..705f251139 100644
--- a/src/components/utils/src/signals_linux.cc
+++ b/src/components/utils/src/signals_linux.cc
@@ -35,33 +35,58 @@
#include "utils/signals.h"
-namespace utils {
+bool utils::UnsibscribeFromTermination() {
+ // Disable some system signals receiving in thread
+ // by blocking those signals
+ // (system signals processes only in the main thread)
+ // Mustn't block all signals!
+ // See "Advanced Programming in the UNIX Environment, 3rd Edition"
+ // (http://poincare.matf.bg.ac.rs/~ivana//courses/ps/sistemi_knjige/pomocno/apue.pdf,
+ // "12.8. Threads and Signals".
+ sigset_t signal_set;
+ sigemptyset(&signal_set);
+ sigaddset(&signal_set, SIGINT);
+ sigaddset(&signal_set, SIGTERM);
+ sigaddset(&signal_set, SIGSEGV);
+ return pthread_sigmask(SIG_BLOCK, &signal_set, NULL);
+}
-bool SubscribeToInterruptSignal(sighandler_t func) {
+namespace {
+void CatchSIGSEGV(sighandler_t handler) {
struct sigaction act;
- act.sa_handler = func;
+ sigset_t signal_set;
+ act.sa_handler = handler;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
+ sigemptyset(&signal_set);
+ sigaddset(&signal_set, SIGSEGV);
- return sigaction(SIGINT, &act, NULL) == 0;
+ sigaction(SIGSEGV, &act, NULL);
}
+} // namespace
-bool SubscribeToTerminateSignal(sighandler_t func) {
- struct sigaction act;
- act.sa_handler = func;
- sigemptyset(&act.sa_mask);
- act.sa_flags = 0;
+bool utils::WaitTerminationSignals(sighandler_t sig_handler) {
+ sigset_t signal_set;
+ int sig = -1;
- return sigaction(SIGTERM, &act, NULL) == 0;
-}
+ sigemptyset(&signal_set);
+ sigaddset(&signal_set, SIGINT);
+ sigaddset(&signal_set, SIGTERM);
+ sigaddset(&signal_set, SIGSEGV);
-bool SubscribeToFaultSignal(sighandler_t func) {
- struct sigaction act;
- act.sa_handler = func;
- sigemptyset(&act.sa_mask);
- act.sa_flags = 0;
+ if (!sigwait(&signal_set, &sig)) {
+ // unblock SIGSEGV to catch him later
+ sigemptyset(&signal_set);
+ sigaddset(&signal_set, SIGSEGV);
+ pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL);
- return sigaction(SIGSEGV, &act, NULL) == 0;
+ // Catch possible crashes on exit
+ // after e.g. sigint was caught
+ if (sig != SIGSEGV) {
+ CatchSIGSEGV(sig_handler);
+ }
+ sig_handler(sig);
+ return true;
+ }
+ return false;
}
-
-} // namespace utils
diff --git a/src/components/utils/src/threads/posix_thread.cc b/src/components/utils/src/threads/posix_thread.cc
index c8a01d8848..5e8d609b67 100644
--- a/src/components/utils/src/threads/posix_thread.cc
+++ b/src/components/utils/src/threads/posix_thread.cc
@@ -78,23 +78,6 @@ void* Thread::threadFunc(void* arg) {
// running = 1
// finalized = 1
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
- // Disable some system signals receiving in thread
- // by blocking those signals
- // (system signals processes only in the main thread)
- // Mustn't block all signals!
- // See "Advanced Programming in the UNIX Environment, 3rd Edition"
- // (http://poincare.matf.bg.ac.rs/~ivana//courses/ps/sistemi_knjige/pomocno/apue.pdf,
- // "12.8. Threads and Signals".
- sigset_t set;
- sigemptyset(&set);
- sigaddset(&set, SIGINT);
- sigaddset(&set, SIGTERM);
- sigaddset(&set, SIGSEGV);
- if(pthread_sigmask(SIG_BLOCK, &set, NULL) != 0){
- LOG4CXX_ERROR(logger_, "Set thread signal mask error");
- }
- LOG4CXX_DEBUG(logger_,
- "Thread #" << pthread_self() << " started successfully");
threads::Thread* thread = reinterpret_cast<Thread*>(arg);
DCHECK(thread);