Add signal processing 35/24035/5
authorAdam Malinowski <a.malinowsk2@partner.samsung.com>
Mon, 7 Jul 2014 13:22:02 +0000 (15:22 +0200)
committerGerrit Code Review <gerrit@review.vlan103.tizen.org>
Mon, 14 Jul 2014 22:27:07 +0000 (15:27 -0700)
For now only SIGTERM is processed to kindly stop the service.

Change-Id: If754002a8af9f8ca70323f22b06fbd22da0ddb19

12 files changed:
src/common/CMakeLists.txt
src/common/protocol/ProtocolSignal.cpp
src/common/protocol/ProtocolSignal.h
src/common/request/RequestTaker.cpp
src/common/request/RequestTaker.h
src/common/request/SignalRequest.cpp [new file with mode: 0644]
src/common/request/SignalRequest.h [new file with mode: 0644]
src/common/request/pointers.h
src/service/logic/Logic.cpp
src/service/logic/Logic.h
src/service/sockets/SocketManager.cpp
src/service/sockets/SocketManager.h

index 4962b78..9e7cece 100644 (file)
@@ -33,6 +33,7 @@ SET(COMMON_SOURCES
     ${COMMON_PATH}/protocol/ProtocolSignal.cpp
     ${COMMON_PATH}/request/CheckRequest.cpp
     ${COMMON_PATH}/request/RequestTaker.cpp
+    ${COMMON_PATH}/request/SignalRequest.cpp
     ${COMMON_PATH}/response/CheckResponse.cpp
     ${COMMON_PATH}/response/ResponseTaker.cpp
     ${COMMON_PATH}/sockets/Socket.cpp
index 9a30455..2ca6be8 100644 (file)
 /*
  * @file        ProtocolSignal.cpp
  * @author      Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
+ * @author      Adam Malinowski <a.malinowsk2@partner.samsung.com>
  * @version     1.0
  * @brief       This file implements protocol class for signals
  */
 
-#include <common.h>
 #include <memory>
+#include <sys/signalfd.h>
+
+#include <common.h>
+#include <exceptions/NotImplementedException.h>
+#include <request/SignalRequest.h>
+
 #include "ProtocolSignal.h"
 
 namespace Cynara {
@@ -32,18 +38,26 @@ ProtocolSignal::ProtocolSignal() {
 ProtocolSignal::~ProtocolSignal() {
 }
 
+void ProtocolSignal::execute(RequestContextPtr context UNUSED, SignalRequestPtr request UNUSED) {
+    throw NotImplementedException();
+}
+
 ProtocolPtr ProtocolSignal::clone(void) {
     return std::make_shared<ProtocolSignal>();
 }
 
 RequestPtr ProtocolSignal::extractRequestFromBuffer(BinaryQueue &bufferQueue) {
-    TODO_USE_ME(bufferQueue);
-    return RequestPtr(nullptr);
+    if (bufferQueue.size() >= sizeof(struct signalfd_siginfo)) {
+        struct signalfd_siginfo sigInfo;
+        bufferQueue.flattenConsume(&sigInfo, sizeof(sigInfo));
+        return std::make_shared<SignalRequest>(sigInfo);
+    }
+
+    return nullptr;
 }
 
-ResponsePtr ProtocolSignal::extractResponseFromBuffer(BinaryQueue &bufferQueue) {
-    TODO_USE_ME(bufferQueue);
-    return ResponsePtr(nullptr);
+ResponsePtr ProtocolSignal::extractResponseFromBuffer(BinaryQueue &bufferQueue UNUSED) {
+    throw NotImplementedException();
 }
 
 } // namespace Cynara
index bd14478..a9f96aa 100644 (file)
@@ -23,6 +23,8 @@
 #ifndef SRC_COMMON_PROTOCOL_PROTOCOLSIGNAL_H_
 #define SRC_COMMON_PROTOCOL_PROTOCOLSIGNAL_H_
 
+#include <request/pointers.h>
+
 #include "Protocol.h"
 
 namespace Cynara {
@@ -36,6 +38,8 @@ public:
 
     virtual RequestPtr extractRequestFromBuffer(BinaryQueue &bufferQueue);
     virtual ResponsePtr extractResponseFromBuffer(BinaryQueue &bufferQueue);
+
+    virtual void execute(RequestContextPtr context, SignalRequestPtr request);
 };
 
 } // namespace Cynara
index 1725049..4ed8e7f 100644 (file)
@@ -23,7 +23,6 @@
 
 #include <attributes/attributes.h>
 #include <exceptions/NotImplementedException.h>
-#include <request/CheckRequest.h>
 #include <request/RequestContext.h>
 
 #include "RequestTaker.h"
@@ -34,4 +33,8 @@ void RequestTaker::execute(RequestContextPtr context UNUSED, CheckRequestPtr req
     throw NotImplementedException();
 }
 
+void RequestTaker::execute(RequestContextPtr context UNUSED, SignalRequestPtr request UNUSED) {
+    throw NotImplementedException();
+}
+
 } // namespace Cynara
index 581d342..1739ba6 100644 (file)
@@ -33,6 +33,7 @@ public:
     virtual ~RequestTaker() = default;
 
     virtual void execute(RequestContextPtr context, CheckRequestPtr request);
+    virtual void execute(RequestContextPtr context, SignalRequestPtr request);
 };
 
 } // namespace Cynara
diff --git a/src/common/request/SignalRequest.cpp b/src/common/request/SignalRequest.cpp
new file mode 100644 (file)
index 0000000..852655e
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+/*
+ * @file        SignalRequest.cpp
+ * @author      Adam Malinowski <a.malinowsk2@partner.samsung.com>
+ * @version     1.0
+ * @brief       This file implements signal request class
+ */
+
+#include <memory>
+
+#include "SignalRequest.h"
+
+namespace Cynara {
+
+void SignalRequest::execute(RequestPtr self, RequestTakerPtr taker,
+                            RequestContextPtr context) const {
+    taker->execute(context, std::dynamic_pointer_cast<SignalRequest>(self));
+}
+
+} // namespace Cynara
diff --git a/src/common/request/SignalRequest.h b/src/common/request/SignalRequest.h
new file mode 100644 (file)
index 0000000..f9d1422
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+/*
+ * @file        SignalRequest.h
+ * @author      Adam Malinowski <a.malinowsk2@partner.samsung.com>
+ * @version     1.0
+ * @brief       This file defines signal request class
+ */
+
+#ifndef SRC_COMMON_REQUEST_SIGNALREQUEST_H_
+#define SRC_COMMON_REQUEST_SIGNALREQUEST_H_
+
+#include <sys/signalfd.h>
+
+#include <request/pointers.h>
+#include <request/Request.h>
+
+namespace Cynara {
+
+class SignalRequest : public Request {
+private:
+    struct signalfd_siginfo m_sigInfo;
+
+public:
+    SignalRequest(struct signalfd_siginfo sigInfo) : Request(0), m_sigInfo(sigInfo) {
+    }
+
+    virtual ~SignalRequest() = default;
+
+    virtual void execute(RequestPtr self, RequestTakerPtr taker, RequestContextPtr context) const;
+
+    uint32_t signalNumber(void) {
+        return m_sigInfo.ssi_signo;
+    }
+
+    struct signalfd_siginfo &sigInfo(void) {
+        return m_sigInfo;
+    }
+};
+
+} // namespace Cynara
+
+#endif /* SRC_COMMON_REQUEST_SIGNALREQUEST_H_ */
index c492336..b3c22e7 100644 (file)
@@ -39,6 +39,9 @@ typedef std::shared_ptr<RequestContext> RequestContextPtr;
 class RequestTaker;
 typedef std::shared_ptr<RequestTaker> RequestTakerPtr;
 
+class SignalRequest;
+typedef std::shared_ptr<SignalRequest> SignalRequestPtr;
+
 } // namespace Cynara
 
 #endif /* SRC_COMMON_REQUEST_POINTERS_H_ */
index a4de76b..40e2905 100644 (file)
 #include <log/log.h>
 #include <common.h>
 #include <exceptions/PluginNotFoundException.h>
+#include <signal.h>
 
 #include <main/Cynara.h>
 #include <request/CheckRequest.h>
 #include <request/RequestContext.h>
+#include <request/SignalRequest.h>
 #include <response/CheckResponse.h>
 #include <storage/Storage.h>
 
+#include <sockets/SocketManager.h>
+
 #include "Logic.h"
 
 namespace Cynara {
@@ -39,6 +43,17 @@ Logic::Logic() {
 Logic::~Logic() {
 }
 
+void Logic::execute(RequestContextPtr context UNUSED, SignalRequestPtr request) {
+    LOGD("Processing signal: [%d]", request->signalNumber());
+
+    switch (request->signalNumber()) {
+    case SIGTERM:
+        LOGI("SIGTERM received!");
+        m_socketManager->mainLoopStop();
+        break;
+    }
+}
+
 void Logic::execute(RequestContextPtr context, CheckRequestPtr request) {
     PolicyResult result(PredefinedPolicyType::DENY);
     if (check(context, request->key(), result)) {
index da4654c..a9d6cb9 100644 (file)
@@ -51,6 +51,7 @@ public:
     }
 
     virtual void execute(RequestContextPtr context, CheckRequestPtr request);
+    virtual void execute(RequestContextPtr context, SignalRequestPtr request);
 
 private:
     StoragePtr m_storage;
index 7c7adeb..55edc02 100644 (file)
@@ -16,6 +16,7 @@
 /*
  * @file        SocketManager.cpp
  * @author      Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
+ * @author      Adam Malinowski <a.malinowsk2@partner.samsung.com>
  * @version     1.0
  * @brief       This file implements socket layer manager for cynara
  */
@@ -23,7 +24,9 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <memory>
+#include <signal.h>
 #include <sys/select.h>
+#include <sys/signalfd.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
 #include <sys/types.h>
@@ -73,7 +76,7 @@ void SocketManager::init(void) {
 
     createDomainSocket(std::make_shared<ProtocolClient>(), clientSocketPath, clientSocketUMask);
     createDomainSocket(std::make_shared<ProtocolAdmin>(), adminSocketPath, adminSocketUMask);
-    // todo create signal descriptor
+    createSignalSocket(std::make_shared<ProtocolSignal>());
     LOGI("SocketManger init done");
 }
 
@@ -327,6 +330,33 @@ int SocketManager::getSocketFromSystemD(const std::string &path) {
     return -1;
 }
 
+void SocketManager::createSignalSocket(ProtocolPtr protocol) {
+    sigset_t mask;
+
+    // Maybe someone will find useful some kind of registering signals with callbacks
+    // but for now I'm making it as simple as possible.
+    sigemptyset(&mask);
+    sigaddset(&mask, SIGTERM); // systemd terminates service sending this signal
+
+    if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) {
+        LOGE("sigprocmask failed: <%s>", strerror(errno));
+        return;
+    }
+
+    int fd = signalfd(-1, &mask, SFD_NONBLOCK);
+    if (fd < 0) {
+        LOGE("Creating signal file descriptor failed: <%s>", strerror(errno));
+        return;
+    }
+
+    auto &desc = createDescriptor(fd);
+    desc.setListen(false);
+    desc.setProtocol(protocol);
+    addReadSocket(fd);
+
+    LOGD("Signal socket: [%d] added.", fd);
+}
+
 Descriptor &SocketManager::createDescriptor(int fd) {
     if (fd > m_maxDesc) {
         m_maxDesc = fd;
index 6112963..2acd810 100644 (file)
@@ -78,6 +78,7 @@ private:
     void createDomainSocket(ProtocolPtr protocol, const std::string &path, mode_t mask);
     int createDomainSocketHelp(const std::string &path, mode_t mask);
     int getSocketFromSystemD(const std::string &path);
+    void createSignalSocket(ProtocolPtr protocol);
 
     Descriptor &createDescriptor(int fd);