From: Sangyoon Jang Date: Thu, 16 Mar 2017 06:14:07 +0000 (+0900) Subject: Use signalfd to handle SIGCHLD X-Git-Tag: accepted/tizen/common/20170322.154049~2 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fappfw%2Fpkgmgr-server.git;a=commitdiff_plain;h=70419b648b9a8671a4003d9583b9fb63eb349100 Use signalfd to handle SIGCHLD Change-Id: I6e6327508e074919d7347afdafdb13fa9555c13b Signed-off-by: Sangyoon Jang --- diff --git a/src/pkgmgr-server.c b/src/pkgmgr-server.c index cf55a28..38334d9 100644 --- a/src/pkgmgr-server.c +++ b/src/pkgmgr-server.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -82,14 +83,8 @@ is dynamically determined. static char backend_busy = 0; extern int num_of_backends; -struct signal_info_t { - pid_t pid; - int status; -}; - -static int pipe_sig[2]; -static GIOChannel *pipe_io; -static guint pipe_wid; +static GIOChannel *sio; +static guint swid; static GHashTable *backend_info_table; static GMainLoop *mainloop; @@ -98,7 +93,6 @@ static int __check_queue_status_for_exit(void); static int __is_backend_busy(int position); static void __set_backend_busy(int position); static void __set_backend_free(int position); -static void sighandler(int signo); gboolean exit_server(void *data); @@ -179,39 +173,42 @@ static int __setup_size_info_io(struct backend_job *job) return 0; } -static gboolean pipe_io_handler(GIOChannel *io, GIOCondition cond, +static gboolean __signal_handler(GIOChannel *io, GIOCondition cond, gpointer data) { GError *err = NULL; GIOStatus s; gsize len; - struct signal_info_t info; + struct signalfd_siginfo fdsi; struct backend_job *job; + pid_t pid; + int status; - s = g_io_channel_read_chars(io, (gchar *)&info, - sizeof(struct signal_info_t), &len, &err); - if (s != G_IO_STATUS_NORMAL) { - ERR("Signal pipe read failed: %s", err->message); + s = g_io_channel_read_chars(io, (gchar *)&fdsi, + sizeof(struct signalfd_siginfo), &len, &err); + if (s != G_IO_STATUS_NORMAL || len != sizeof(struct signalfd_siginfo)) { + ERR("Signal read failed"); g_error_free(err); return TRUE; } + pid = waitpid(-1, &status, WNOHANG); job = (struct backend_job *)g_hash_table_lookup(backend_info_table, - (gconstpointer)info.pid); + (gconstpointer)pid); if (job == NULL) { ERR("Unknown child exit"); return -1; } __set_backend_free(job->backend_slot); - if (WIFSIGNALED(info.status)) { + if (WIFSIGNALED(status)) { _send_fail_signal(job); - DBG("backend[%s] exit with signal[%d]", job->backend_type, - WTERMSIG(info.status)); - } else if (WEXITSTATUS(info.status)) { - DBG("backend[%s] exit with error", job->backend_type); + DBG("backend[%s][%d] exit with signal[%d]", job->backend_type, + pid, WTERMSIG(status)); + } else if (WEXITSTATUS(status)) { + DBG("backend[%s][%d] exit with error", job->backend_type, pid); } else { - DBG("backend[%s] exit", job->backend_type); + DBG("backend[%s][%d] exit", job->backend_type, pid); } if (job->extra) { @@ -222,7 +219,7 @@ static gboolean pipe_io_handler(GIOChannel *io, GIOCondition cond, } } - g_hash_table_remove(backend_info_table, (gconstpointer)info.pid); + g_hash_table_remove(backend_info_table, (gconstpointer)pid); g_idle_add(queue_job, NULL); return TRUE; @@ -234,60 +231,42 @@ static int __init_backend_info(void) g_direct_equal, NULL, (GDestroyNotify)_free_backend_job); - if (pipe(pipe_sig)) { - ERR("create pipe failed"); - return -1; - } - - pipe_io = g_io_channel_unix_new(pipe_sig[0]); - g_io_channel_set_encoding(pipe_io, NULL, NULL); - g_io_channel_set_buffered(pipe_io, FALSE); - pipe_wid = g_io_add_watch(pipe_io, G_IO_IN, pipe_io_handler, NULL); - return 0; } static void __fini_backend_info(void) { - g_source_remove(pipe_wid); - g_io_channel_unref(pipe_io); - close(pipe_sig[0]); - close(pipe_sig[1]); - /*Free backend info */ g_hash_table_destroy(backend_info_table); } -static void sighandler(int signo) -{ - struct signal_info_t info; - char buf[1024] = {0, }; - - info.pid = waitpid(-1, &info.status, WNOHANG); - if (write(pipe_sig[1], &info, sizeof(struct signal_info_t)) < 0) - ERR("failed to write result: %s", - strerror_r(errno, buf, sizeof(buf))); -} - static int __register_signal_handler(void) { - static int sig_reg = 0; - struct sigaction act; + sigset_t mask; + int sfd; - if (sig_reg) - return 0; + sigemptyset(&mask); + sigaddset(&mask, SIGCHLD); + + if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) { + ERR("sigprocmask failed"); + return -1; + } - act.sa_handler = sighandler; - sigemptyset(&act.sa_mask); - act.sa_flags = SA_NOCLDSTOP; - if (sigaction(SIGCHLD, &act, NULL) < 0) { - ERR("signal: SIGCHLD failed"); + sfd = signalfd(-1, &mask, SFD_NONBLOCK); + if (sfd == -1) { + ERR("signalfd failed"); return -1; } + sio = g_io_channel_unix_new(sfd); + g_io_channel_set_close_on_unref(sio, TRUE); + g_io_channel_set_encoding(sio, NULL, NULL); + g_io_channel_set_buffered(sio, FALSE); + swid = g_io_add_watch(sio, G_IO_IN, __signal_handler, NULL); + g_timeout_add_seconds(2, exit_server, NULL); - sig_reg = 1; return 0; } @@ -1691,6 +1670,11 @@ int main(int argc, char *argv[]) DBG("server start"); + if (__register_signal_handler()) { + ERR("failed to register signal handler"); + return -1; + } + r = _init_backend_queue(); if (r) { DBG("Queue Initialization Failed"); @@ -1709,11 +1693,6 @@ int main(int argc, char *argv[]) return -1; } - if (__register_signal_handler()) { - ERR("failed to register signal handler"); - return -1; - } - #if !GLIB_CHECK_VERSION(2, 35, 0) g_type_init(); #endif @@ -1732,6 +1711,9 @@ int main(int argc, char *argv[]) __fini_backend_info(); _fini_backend_queue(); + g_source_remove(swid); + g_io_channel_unref(sio); + DBG("package manager server terminated."); return 0;