From 707a076a0698ffc7048dd0fe933175cb7065c3d3 Mon Sep 17 00:00:00 2001 From: Adam Malinowski Date: Wed, 10 Dec 2014 10:50:15 +0100 Subject: [PATCH] Implement stopping daemon This patch implements proper daemon stopping for correct handling 'systemd stop' procedure. Change-Id: I6b0ad7d7978e5ffbe73383e5fcb27d3fe5717539 --- src/agent/main/Agent.cpp | 32 ++++++++++++++++++++++++++----- src/agent/main/CynaraTalker.cpp | 12 +++++++++++- src/agent/main/main.cpp | 19 ++++++++++++++++++ src/agent/ui/AskUINotificationBackend.cpp | 10 ++++++++++ 4 files changed, 67 insertions(+), 6 deletions(-) diff --git a/src/agent/main/Agent.cpp b/src/agent/main/Agent.cpp index e8aaba9..1855952 100644 --- a/src/agent/main/Agent.cpp +++ b/src/agent/main/Agent.cpp @@ -19,6 +19,8 @@ * @brief This file implements main class of ask user agent */ +#include +#include #include #include #include @@ -60,7 +62,11 @@ void Agent::run() { while (!m_stopFlag) { std::unique_lock lock(m_mutex); - m_event.wait(lock); + m_event.wait_for(lock, std::chrono::milliseconds(1000)); + + if (m_stopFlag) { + break; + } while (!m_incomingRequests.empty() || !m_incomingResponses.empty()) { @@ -103,16 +109,32 @@ void Agent::run() { cleanupUIThreads(); lock.lock(); } - } - //TODO: dismiss all threads if possible - LOGD("Agent task stopped"); } void Agent::finish() { - m_cynaraTalker.stop(); + if (!m_cynaraTalker.stop()) { + LOGE("Cynara talker thread could not be stopped. Calling quick_exit()"); + quick_exit(EXIT_SUCCESS); + } + + while (!m_incomingRequests.empty()) { + Request *request = m_incomingRequests.front(); + m_incomingRequests.pop(); + delete request; + } + + if (!cleanupUIThreads()) { + LOGE("At least one of UI threads could not be stopped. Calling quick_exit()"); + quick_exit(EXIT_SUCCESS); + } + + for (auto it = m_requests.begin(); it != m_requests.end();) { + delete it->second; + it = m_requests.erase(it); + } LOGD("Agent daemon has stopped commonly"); } diff --git a/src/agent/main/CynaraTalker.cpp b/src/agent/main/CynaraTalker.cpp index 28efe12..571cada 100644 --- a/src/agent/main/CynaraTalker.cpp +++ b/src/agent/main/CynaraTalker.cpp @@ -19,6 +19,7 @@ * @brief This file implements class of cynara talker */ +#include #include #include @@ -101,7 +102,16 @@ bool CynaraTalker::stop() { } void CynaraTalker::run() { - int ret = cynara_agent_initialize(&m_cynara, SupportedTypes::Agent::AgentType); + int ret; + sigset_t mask; + + sigemptyset(&mask); + sigaddset(&mask, SIGTERM); + if ((ret = sigprocmask(SIG_BLOCK, &mask, nullptr)) < 0) { + LOGE("sigprocmask failed [<<" << ret << "]"); + } + + ret = cynara_agent_initialize(&m_cynara, SupportedTypes::Agent::AgentType); if (ret != CYNARA_API_SUCCESS) { LOGE("Initialization of cynara structure failed with error: [" << ret << "]"); m_requestHandler(new Request(RT_Close, 0, nullptr, 0)); // Notify agent he should die diff --git a/src/agent/main/main.cpp b/src/agent/main/main.cpp index 34d8d6c..0383d18 100644 --- a/src/agent/main/main.cpp +++ b/src/agent/main/main.cpp @@ -20,7 +20,9 @@ */ #include +#include #include +#include #include #include #include @@ -30,9 +32,26 @@ #include "Agent.h" +// Handle kill message from systemd +void kill_handler(int sig UNUSED) { + LOGD("Ask user agent service is going down now"); + AskUser::Agent::Agent::stop(); +} + int main(int argc UNUSED, char **argv UNUSED) { init_log(); + int ret; + struct sigaction act; + + // Install kill handler - TERM signal will be delivered form systemd to kill this service + memset(&act, 0, sizeof(act)); + act.sa_handler = &kill_handler; + if ((ret = sigaction(SIGTERM, &act, NULL)) < 0) { + LOGE("sigaction failed [<<" << ret << "]"); + return EXIT_FAILURE; + } + char *locale = setlocale(LC_ALL, ""); LOGD("Current locale is: <" << locale << ">"); diff --git a/src/agent/ui/AskUINotificationBackend.cpp b/src/agent/ui/AskUINotificationBackend.cpp index 746081d..fd8e81c 100644 --- a/src/agent/ui/AskUINotificationBackend.cpp +++ b/src/agent/ui/AskUINotificationBackend.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -207,6 +208,15 @@ bool AskUINotificationBackend::dismiss() { } void AskUINotificationBackend::run() { + int ret; + sigset_t mask; + + sigemptyset(&mask); + sigaddset(&mask, SIGTERM); + if ((ret = sigprocmask(SIG_BLOCK, &mask, nullptr)) < 0) { + LOGE("sigprocmask failed [<<" << ret << "]"); + } + try { int buttonClicked = 0; notification_error_e ret = notification_wait_response(m_notification, m_responseTimeout, -- 2.7.4