#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <sys/signalfd.h>
#include <signal.h>
#include <grp.h>
#include <fcntl.h>
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;
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);
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) {
}
}
- 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;
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;
}
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");
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
__fini_backend_info();
_fini_backend_queue();
+ g_source_remove(swid);
+ g_io_channel_unref(sio);
+
DBG("package manager server terminated.");
return 0;