Ignoring SIGTERM 48/43948/2
authorJan Olszak <j.olszak@samsung.com>
Wed, 15 Jul 2015 12:54:10 +0000 (14:54 +0200)
committerDariusz Michaluk <d.michaluk@samsung.com>
Wed, 15 Jul 2015 13:38:56 +0000 (06:38 -0700)
[Feature]       N/A
[Cause]         N/A
[Solution]      N/A
[Verification]  Build, install, run tests

Change-Id: Ib81c67dc0738db5ef4713d6d8b2c2376a8323800

common/utils/signal.cpp
common/utils/signal.hpp
common/utils/signalfd.cpp
common/utils/signalfd.hpp
server/main.cpp
server/server.cpp
tests/unit_tests/utils/ut-signalfd.cpp

index 17ec003..cdd79e6 100644 (file)
@@ -95,7 +95,7 @@ void signalBlock(const int sigNum)
     changeSignal(SIG_BLOCK, sigNum);
 }
 
-void signalBlockAll()
+void signalBlockAllExcept(const std::initializer_list<int>& signals)
 {
     ::sigset_t set;
     if(-1 == ::sigfillset(&set)) {
@@ -104,6 +104,13 @@ void signalBlockAll()
         throw UtilsException("Error in sigfillset: " + msg);
     }
 
+    for(const int s: signals) {
+        if(-1 == ::sigaddset(&set, s)) {
+            const std::string msg = getSystemErrorMessage();
+            LOGE("Error in sigaddset: " << msg);
+            throw UtilsException("Error in sigaddset: " + msg);
+        }
+    }
     setSignalMask(SIG_BLOCK, set);
 }
 
@@ -112,6 +119,20 @@ void signalUnblock(const int sigNum)
     changeSignal(SIG_UNBLOCK, sigNum);
 }
 
+void signalIgnore(const std::initializer_list<int>& signals)
+{
+    struct ::sigaction act;
+    act.sa_handler = SIG_IGN;
+
+    for(const int s: signals) {
+        if(-1 == ::sigaction(s, &act, nullptr)) {
+            const std::string msg = getSystemErrorMessage();
+            LOGE("Error in sigaction: " << msg);
+            throw UtilsException("Error in sigaction: " + msg);
+        }
+    }
+}
+
 } // namespace utils
 
 
index 4cd5a5a..3ecf166 100644 (file)
 #ifndef COMMON_UTILS_SIGNAL_HPP
 #define COMMON_UTILS_SIGNAL_HPP
 
+#include <initializer_list>
 #include <csignal>
 
 namespace utils {
 
 ::sigset_t getSignalMask();
 bool isSignalBlocked(const int sigNum);
-void signalBlockAll();
+void signalBlockAllExcept(const std::initializer_list<int>& signals);
 void signalBlock(const int sigNum);
 void signalUnblock(const int sigNum);
+void signalIgnore(const std::initializer_list<int>& signals);
 
 } // namespace utils
 
index 0b3250f..6ffa5cb 100644 (file)
@@ -62,6 +62,22 @@ void SignalFD::setHandler(const int sigNum, const Callback&& callback)
 {
     Lock lock(mMutex);
 
+    ::sigset_t set = getSignalMask();
+
+    int error = ::signalfd(mFD, &set, SFD_CLOEXEC);
+    if (error != mFD) {
+        const std::string msg = getSystemErrorMessage();
+        LOGE("Error in signalfd: " << msg);
+        throw UtilsException("Error in signalfd: " + msg);
+    }
+
+    mCallbacks.insert({sigNum, callback});
+}
+
+void SignalFD::setHandlerAndBlock(const int sigNum, const Callback&& callback)
+{
+    Lock lock(mMutex);
+
     bool isBlocked = isSignalBlocked(sigNum);
 
     ::sigset_t set = getSignalMask();
index 5410a34..4efed4b 100644 (file)
@@ -54,7 +54,8 @@ public:
     SignalFD& operator=(const SignalFD&) = delete;
 
     /**
-     * Add a callback for a specified signal
+     * Add a callback for a specified signal.
+     * Doesn't block the signal.
      *
      * @param sigNum number of the signal
      * @param callback handler callback
@@ -62,6 +63,15 @@ public:
     void setHandler(const int sigNum, const Callback&& callback);
 
     /**
+     * Add a callback for a specified signal
+     * Blocks the asynchronous signal handling.
+     *
+     * @param sigNum number of the signal
+     * @param callback handler callback
+     */
+    void setHandlerAndBlock(const int sigNum, const Callback&& callback);
+
+    /**
      * @return signal file descriptor
      */
     int getFD() const;
index 513a4f3..83556b5 100644 (file)
@@ -124,7 +124,10 @@ int main(int argc, char* argv[])
     try {
         // Block all signals
         // Server will unblock handled signals
-        utils::signalBlockAll();
+        utils::signalBlockAllExcept({SIGTERM});
+
+        // TODO: SIGTERM used by lxc, get rid of this
+        utils::signalIgnore({SIGTERM});
 
         Server server(CONFIG_PATH);
         server.run(runAsRoot);
index c8413c7..f48d291 100644 (file)
@@ -82,17 +82,17 @@ Server::Server(const std::string& configPath)
       mConfigPath(configPath),
       mSignalFD(mDispatcher.getPoll())
 {
-    mSignalFD.setHandler(SIGINT, [this](int) {
+    mSignalFD.setHandlerAndBlock(SIGUSR1, [this] (int) {
+        LOGD("Received SIGUSR1 - triggering update.");
+        mIsUpdate = true;
         mStopLatch.set();
     });
 
-    mSignalFD.setHandler(SIGTERM, [this] (int) {
+    mSignalFD.setHandlerAndBlock(SIGINT, [this](int) {
         mStopLatch.set();
     });
 
-    mSignalFD.setHandler(SIGUSR1, [this] (int) {
-        LOGD("Received SIGUSR1 - triggering update.");
-        mIsUpdate = true;
+    mSignalFD.setHandler(SIGTERM, [this] (int) {
         mStopLatch.set();
     });
 }
index 57cf226..9f002e0 100644 (file)
@@ -38,26 +38,27 @@ using namespace utils;
 
 namespace {
 
-volatile sig_atomic_t gAsyncSignal = 0;
+volatile sig_atomic_t gAsyncSignal;
 
 struct Fixture {
     Fixture()
     {
+        gAsyncSignal = 0;
         ::signal(SIGINT, &Fixture::signalHandler);
     }
     ~Fixture()
     {
         ::signal(SIGINT, SIG_DFL);
+        gAsyncSignal = 0;
     }
 
     static void signalHandler(int s)
     {
-        // Signal should never propagate to this handler
         gAsyncSignal = s;
     }
 
-    static bool isSignalHandled() {
-        return gAsyncSignal == 0;
+    static bool isAsyncHandlerCalled() {
+        return gAsyncSignal != 0;
     }
 };
 
@@ -78,12 +79,12 @@ BOOST_AUTO_TEST_CASE(BlockingSignalHandler)
 {
     ipc::epoll::EventPoll poll;
     SignalFD s(poll);
-    s.setHandler(SIGUSR1, [](const int) {});
-    s.setHandler(SIGINT, [](const int) {});
+    s.setHandlerAndBlock(SIGUSR1, [](const int) {});
+    s.setHandlerAndBlock(SIGINT, [](const int) {});
 
     ::raise(SIGINT);
     std::this_thread::sleep_for(std::chrono::milliseconds(TIMEOUT));
-    BOOST_REQUIRE(isSignalHandled());
+    BOOST_REQUIRE(!isAsyncHandlerCalled());
 }
 
 BOOST_AUTO_TEST_CASE(SignalHandler)
@@ -99,7 +100,7 @@ BOOST_AUTO_TEST_CASE(SignalHandler)
     ::raise(SIGINT);
     poll.dispatchIteration(TIMEOUT);
     BOOST_REQUIRE(isSignalCalled);
-    BOOST_REQUIRE(isSignalHandled());
+    BOOST_REQUIRE(!isAsyncHandlerCalled());
 }
 
 BOOST_AUTO_TEST_SUITE_END()