From f3957f2da642de9571cce3c18b7242c22684707a Mon Sep 17 00:00:00 2001 From: "kibak.yoon" Date: Thu, 19 May 2016 11:54:50 +0900 Subject: [PATCH] sensord: terminate sensor daemon safely - 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 --- packaging/sensord.service | 2 - src/server/main.cpp | 12 ++-- src/server/server.cpp | 136 ++++++++++++++++++++++++++++++++++------------ src/server/server.h | 21 ++++++- src/shared/csocket.cpp | 48 +++++++++++++--- src/shared/csocket.h | 1 + 6 files changed, 168 insertions(+), 52 deletions(-) diff --git a/packaging/sensord.service b/packaging/sensord.service index 50dc0ad..5cb2e72 100644 --- a/packaging/sensord.service +++ b/packaging/sensord.service @@ -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 diff --git a/src/server/main.cpp b/src/server/main.cpp index 2ef0bfa..b136d69 100644 --- a/src/server/main.cpp +++ b/src/server/main.cpp @@ -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; } diff --git a/src/server/server.cpp b/src/server/server.cpp index 7a5e416..184df3d 100644 --- a/src/server/server.cpp +++ b/src/server/server.cpp @@ -17,14 +17,17 @@ * */ +#include +#include + #include #include #include #include #include #include -#include #include +#include #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() diff --git a/src/server/server.h b/src/server/server.h index 3f32b3f..3dbd0d4 100644 --- a/src/server/server.h +++ b/src/server/server.h @@ -22,23 +22,35 @@ #include #include +#include +#include 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 client_command_sockets; + std::vector 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); }; diff --git a/src/shared/csocket.cpp b/src/shared/csocket.cpp index 8481333..4a01a38 100644 --- a/src/shared/csocket.cpp +++ b/src/shared/csocket.cpp @@ -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 diff --git a/src/shared/csocket.h b/src/shared/csocket.h index 55582cf..1391531 100644 --- a/src/shared/csocket.h +++ b/src/shared/csocket.h @@ -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; -- 2.7.4