diff options
-rw-r--r-- | src/appMain/life_cycle.cc | 11 | ||||
-rw-r--r-- | src/appMain/main.cc | 6 | ||||
-rw-r--r-- | src/components/utils/include/utils/signals.h | 5 | ||||
-rw-r--r-- | src/components/utils/src/signals_linux.cc | 63 | ||||
-rw-r--r-- | src/components/utils/src/threads/posix_thread.cc | 17 |
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); |