sensord: terminate sensor daemon safely 39/70239/3
authorkibak.yoon <kibak.yoon@samsung.com>
Thu, 19 May 2016 02:54:50 +0000 (11:54 +0900)
committerMu-Woong Lee <muwoong.lee@samsung.com>
Thu, 19 May 2016 05:22:17 +0000 (22:22 -0700)
- checking event by using select() before accept()
  if event is accepted when sensord is terminating, restoring connection has
  a problem that client cannot connect to sensord.
- in server, quit g_main_loop and close socket safely.
- sensord.service : off restart option

Change-Id: Ibb2c9eca3cdc26b9782e93d3a3e0337b0a28f1a0
Signed-off-by: kibak.yoon <kibak.yoon@samsung.com>
packaging/sensord.service
src/server/main.cpp
src/server/server.cpp
src/server/server.h
src/shared/csocket.cpp
src/shared/csocket.h

index 50dc0ad..5cb2e72 100644 (file)
@@ -6,8 +6,6 @@ User=sensor
 Group=input
 Type=notify
 ExecStart=/usr/bin/sensord
-Restart=always
-RestartSec=0
 MemoryLimit=20M
 Sockets=sensord_command.socket
 Sockets=sensord_event.socket
index 2ef0bfa..b136d69 100644 (file)
@@ -34,8 +34,7 @@ static void sig_term_handler(int signo, siginfo_t *info, void *data)
 
        _E("Received SIGTERM(%d) from %s(%d)\n", signo, proc_name, info->si_pid);
 
-       /* TODO: Refactoring */
-       raise(SIGKILL);
+       server::get_instance().stop();
 }
 
 static void signal_init(void)
@@ -51,6 +50,8 @@ static void signal_init(void)
        sig_act.sa_sigaction = sig_term_handler;
        sig_act.sa_flags = SA_SIGINFO;
        sigaction(SIGTERM, &sig_act, NULL);
+       sigaction(SIGABRT, &sig_act, NULL);
+       sigaction(SIGINT, &sig_act, NULL);
 }
 
 static void set_cal_data(void)
@@ -63,7 +64,9 @@ static void set_cal_data(void)
        }
 
        fprintf(fp, "%d", SET_CAL);
-       fclose(fp);
+
+       if (fp)
+               fclose(fp);
 
        _I("Succeeded to set calibration data");
 
@@ -78,12 +81,13 @@ int main(int argc, char *argv[])
 
        set_cal_data();
 
+       /* TODO: loader has to be moved to server */
        sensor_loader::get_instance().load();
 
        server::get_instance().run();
-
        server::get_instance().stop();
 
        _I("Sensord terminated");
+
        return 0;
 }
index 7a5e416..184df3d 100644 (file)
  *
  */
 
+#include <sys/epoll.h>
+#include <sys/socket.h>
+
 #include <systemd/sd-daemon.h>
 #include <server.h>
 #include <sensor_loader.h>
 #include <command_common.h>
 #include <command_worker.h>
 #include <thread>
-#include <sys/epoll.h>
 #include <sensor_event_poller.h>
+#include <client_info_manager.h>
 
 #define SYSTEMD_SOCKET_MAX    2
 
@@ -32,12 +35,12 @@ using std::thread;
 
 server::server()
 : m_mainloop(NULL)
+, m_running(false)
 {
 }
 
 server::~server()
 {
-       stop();
 }
 
 int server::get_systemd_socket(const char *name)
@@ -73,46 +76,77 @@ int server::get_systemd_socket(const char *name)
 void server::accept_command_channel(void)
 {
        command_worker *cmd_worker;
+
        _I("Command channel acceptor is started");
 
-       while (true) {
+       while (m_running) {
                csocket client_command_socket;
 
+               if (!m_command_channel_accept_socket.is_valid()) {
+                       _E("Failed to accept, event_channel_accept_socket is closed");
+                       break;
+               }
+
                if (!m_command_channel_accept_socket.accept(client_command_socket)) {
                        _E("Failed to accept command channel from a client");
                        continue;
                }
 
+               if (!m_running) {
+                       _E("server die");
+                       break;
+               }
+
                _D("New client (socket_fd : %d) connected", client_command_socket.get_socket_fd());
 
+               /* TODO: if socket is closed, it should be erased */
+               client_command_sockets.push_back(client_command_socket);
+
                cmd_worker = new(std::nothrow) command_worker(client_command_socket);
 
                if (!cmd_worker) {
                        _E("Failed to allocate memory");
-                       continue;
+                       break;
                }
 
                if (!cmd_worker->start())
                        delete cmd_worker;
        }
+
+       _I("Command channel acceptor is terminated");
 }
 
 void server::accept_event_channel(void)
 {
-       _I("Event channel acceptor is started");
+       _I("Event channel acceptor is started!");
 
-       while (true) {
+       while (m_running) {
                csocket client_event_socket;
 
+               if (!m_event_channel_accept_socket.is_valid()) {
+                       _E("Failed to accept, event_channel_accept_socket is closed");
+                       break;
+               }
+
                if (!m_event_channel_accept_socket.accept(client_event_socket)) {
                        _E("Failed to accept event channel from a client");
                        continue;
                }
 
+               if (!m_running) {
+                       _E("server die");
+                       break;
+               }
+
+               /* TODO: if socket is closed, it should be erased */
+               client_event_sockets.push_back(client_event_socket);
+
                _D("New client(socket_fd : %d) connected", client_event_socket.get_socket_fd());
 
                sensor_event_dispatcher::get_instance().accept_event_connections(client_event_socket);
        }
+
+       _I("Event channel acceptor is terminated");
 }
 
 void server::poll_event(void)
@@ -127,32 +161,6 @@ void server::poll_event(void)
        }
 }
 
-void server::run(void)
-{
-       m_mainloop = g_main_loop_new(NULL, false);
-
-       sensor_event_dispatcher::get_instance().run();
-
-       listen_command_channel();
-       listen_event_channel();
-
-       thread event_channel_accepter(&server::accept_event_channel, this);
-       event_channel_accepter.detach();
-
-       thread command_channel_accepter(&server::accept_command_channel, this);
-       command_channel_accepter.detach();
-
-       thread event_poller(&server::poll_event, this);
-       event_poller.detach();
-
-       sd_notify(0, "READY=1");
-
-       g_main_loop_run(m_mainloop);
-       g_main_loop_unref(m_mainloop);
-
-       return;
-}
-
 bool server::listen_command_channel(void)
 {
        int sock_fd = -1;
@@ -221,13 +229,69 @@ bool server::listen_event_channel(void)
        return true;
 }
 
-void server::stop(void)
+void server::close_socket(void)
 {
-       if (m_mainloop)
-               g_main_loop_quit(m_mainloop);
-
        m_command_channel_accept_socket.close();
        m_event_channel_accept_socket.close();
+
+       for (int i = 0; i < client_command_sockets.size(); ++i)
+               client_command_sockets[i].close();
+
+       for (int i = 0; i < client_event_sockets.size(); ++i)
+               client_event_sockets[i].close();
+
+       client_command_sockets.clear();
+       client_event_sockets.clear();
+}
+
+void server::initialize(void)
+{
+       m_running = true;
+       m_mainloop = g_main_loop_new(NULL, false);
+
+       sensor_event_dispatcher::get_instance().run();
+
+       listen_command_channel();
+       listen_event_channel();
+
+       std::thread event_channel_accepter(&server::accept_event_channel, this);
+       event_channel_accepter.detach();
+
+       std::thread command_channel_accepter(&server::accept_command_channel, this);
+       command_channel_accepter.detach();
+
+       std::thread event_poller(&server::poll_event, this);
+       event_poller.detach();
+
+       sd_notify(0, "READY=1");
+
+       g_main_loop_run(m_mainloop);
+}
+
+void server::terminate(void)
+{
+       sensor_event_dispatcher::get_instance().stop();
+
+       close_socket();
+}
+
+void server::run(void)
+{
+       initialize();
+       terminate();
+}
+
+void server::stop(void)
+{
+       _I("Sensord server stopped");
+
+       m_running = false;
+
+       if (m_mainloop) {
+               g_main_loop_quit(m_mainloop);
+               g_main_loop_unref(m_mainloop);
+               m_mainloop = NULL;
+       }
 }
 
 server& server::get_instance()
index 3f32b3f..3dbd0d4 100644 (file)
 
 #include <glib.h>
 #include <csocket.h>
+#include <vector>
+#include <thread>
 
 class server {
 public:
+       static server& get_instance();
+
+public:
        void run(void);
        void stop(void);
-       static server& get_instance();
 
 private:
        GMainLoop *m_mainloop;
        csocket m_command_channel_accept_socket;
        csocket m_event_channel_accept_socket;
 
+       std::vector<csocket> client_command_sockets;
+       std::vector<csocket> client_event_sockets;
+
+       bool m_running;
+
+private:
        server();
-       ~server();
+       virtual ~server();
+
+       void initialize(void);
+       void terminate(void);
 
        void poll_event(void);
-       void accept_client(void);
 
        bool listen_command_channel(void);
        bool listen_event_channel(void);
@@ -46,6 +58,9 @@ private:
        void accept_command_channel(void);
        void accept_event_channel(void);
 
+       void close_socket(void);
+
+       /* TODO: move to socket class */
        int get_systemd_socket(const char *name);
 };
 
index 8481333..4a01a38 100644 (file)
@@ -130,9 +130,46 @@ bool csocket::listen(const int max_connections)
 
 bool csocket::accept(csocket& client_socket) const
 {
+       const int TIMEOUT = 1;
+       struct timeval tv;
        int addr_length = sizeof(m_addr);
        int err = 0;
 
+       fd_set read_fds;
+
+       while (true) {
+               FD_ZERO(&read_fds);
+               FD_SET(m_sock_fd, &read_fds);
+
+               tv.tv_sec = TIMEOUT;
+               tv.tv_usec = 0;
+
+               err = ::select(m_sock_fd + 1, &read_fds, NULL, NULL, &tv);
+               if (err == -1) {
+                       _ERRNO(errno, _E, "Failed to select(), m_sock_fd : %d", m_sock_fd);
+                       return false;
+               }
+
+               if (!is_valid()) {
+                       _E("socket is closed, m_sock_fd : %d", m_sock_fd);
+                       return false;
+               }
+
+               /* timeout */
+               if (!err)
+                       continue;
+
+               if (FD_ISSET(m_sock_fd, &read_fds))
+                       break;
+
+               _ERRNO(errno, _E, "Failed to select(), msock_fd : %d", m_sock_fd);
+       }
+
+       if (!is_valid()) {
+               _E("socket is closed, m_sock_fd : %d", m_sock_fd);
+               return false;
+       }
+
        do {
                client_socket.m_sock_fd = ::accept(m_sock_fd, (sockaddr *)&m_addr, (socklen_t *)&addr_length);
                if (!client_socket.is_valid())
@@ -169,7 +206,7 @@ ssize_t csocket::recv_for_seqpacket(void* buffer, size_t size) const
        ssize_t err, len;
 
        do {
-        len = ::recv(m_sock_fd, buffer, size, m_recv_flags);
+               len = ::recv(m_sock_fd, buffer, size, m_recv_flags);
 
                if (len > 0) {
                        err = 0;
@@ -180,20 +217,17 @@ ssize_t csocket::recv_for_seqpacket(void* buffer, size_t size) const
                } else {
                        err = errno;
                }
-    } while (err == EINTR);
+       } while (err == EINTR);
 
-       if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
-               _ERRNO(err, _D, "Failed to recv(%d, %#x, %d, %#x) = %d",
-                       m_socket_fd, buffer, size, m_recv_flags, len);
+       if ((err == EAGAIN) || (err == EWOULDBLOCK))
                return 0;
-       }
 
        if (err) {
                _ERRNO(err, _E, "Failed to recv(%d, %#x, %d, %#x) = %d",
                        m_sock_fd, buffer, size, m_recv_flags, len);
        }
 
-    return err == 0 ? len : -err;
+       return err == 0 ? len : -err;
 }
 
 ssize_t csocket::send_for_stream(const void *buffer, size_t size) const
index 55582cf..1391531 100644 (file)
@@ -69,6 +69,7 @@ private:
        ssize_t recv_for_seqpacket(void* buffer, size_t size) const;
        ssize_t recv_for_stream(void* buffer, size_t size) const;
 
+private:
        int m_sock_fd;
        int m_sock_type;
        sockaddr_un m_addr;