summaryrefslogtreecommitdiff
path: root/src/components/utils/src/signals_linux.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/utils/src/signals_linux.cc')
-rw-r--r--src/components/utils/src/signals_linux.cc54
1 files changed, 37 insertions, 17 deletions
diff --git a/src/components/utils/src/signals_linux.cc b/src/components/utils/src/signals_linux.cc
index 2e598d1b0f..274c254716 100644
--- a/src/components/utils/src/signals_linux.cc
+++ b/src/components/utils/src/signals_linux.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Ford Motor Company
+ * Copyright (c) 2016, Ford Motor Company
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,29 +35,49 @@
#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);
-bool SubscribeToTerminateSignal(sighandler_t func) {
+ return !pthread_sigmask(SIG_BLOCK, &signal_set, NULL);
+}
+
+namespace {
+bool CatchSIGSEGV(sighandler_t handler) {
struct sigaction act;
- act.sa_handler = func;
+
+ act.sa_handler = handler;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
- bool sigint_subscribed = (sigaction(SIGINT, &act, NULL) == 0);
- bool sigterm_subscribed = (sigaction(SIGTERM, &act, NULL) == 0);
-
- return sigint_subscribed && sigterm_subscribed;
+ return !sigaction(SIGSEGV, &act, NULL);
}
+} // namespace
-bool SubscribeToFaultSignal(sighandler_t func) {
- struct sigaction act;
- act.sa_handler = func;
- sigemptyset(&act.sa_mask);
- act.sa_flags = SA_RESETHAND; // we only want to catch SIGSEGV once to flush logger queue
+bool utils::WaitTerminationSignals(sighandler_t sig_handler) {
+ sigset_t signal_set;
+ int sig = -1;
- bool sigsegv_subscribed = (sigaction(SIGSEGV, &act, NULL) == 0);
+ sigemptyset(&signal_set);
+ sigaddset(&signal_set, SIGINT);
+ sigaddset(&signal_set, SIGTERM);
- return sigsegv_subscribed;
-}
+ if (!CatchSIGSEGV(sig_handler)) {
+ return false;
+ }
-} // namespace utils
+ if (!sigwait(&signal_set, &sig)) {
+ sig_handler(sig);
+ return true;
+ }
+ return false;
+}