From 853fefbb9663a5d6003cdefbc16c19c67d5bfcc7 Mon Sep 17 00:00:00 2001 From: Alban Crequy Date: Fri, 16 Mar 2012 15:32:51 +0000 Subject: Add mcd_service_stop() and stop the McdService when SIGINT is sent https://bugs.freedesktop.org/show_bug.cgi?id=47054 --- server/mc-server.c | 115 ++++++++++++++++++++++++++++++++++++++++++++++++++--- src/mcd-service.c | 6 +++ src/mcd-service.h | 1 + 3 files changed, 117 insertions(+), 5 deletions(-) diff --git a/server/mc-server.c b/server/mc-server.c index a830c81e..033ef873 100644 --- a/server/mc-server.c +++ b/server/mc-server.c @@ -26,29 +26,120 @@ #include #include +#ifdef G_OS_UNIX +#include +#include +#include +#include +#include +#include +#include +#endif + #include #include #include "mcd-service.h" static TpDebugSender *debug_sender; +static McdService *mcd = NULL; + +#ifdef G_OS_UNIX +static int quit_pipe[2]; +#define QUIT_READ_END 0 +#define QUIT_WRITE_END 1 +#endif #ifdef BUILD_AS_ANDROID_SERVICE int telepathy_mission_control_main (int argc, char **argv); #endif static void -on_abort (McdService * mcd) +on_abort (McdService * _mcd) { g_debug ("Exiting now ..."); - mcd_debug_print_tree (mcd); + mcd_debug_print_tree (_mcd); - g_object_unref (mcd); g_debug ("MC now exits .. bye bye"); - exit (0); + mcd_service_stop (_mcd); +} + +#ifdef G_OS_UNIX +static void +signal_handler (int sig) +{ + switch (sig) + { + case SIGINT: + if ((quit_pipe[QUIT_WRITE_END] > 0) && + write (quit_pipe[QUIT_WRITE_END], "\0", 1) != 1) + { + /* If we can't write to the socket, dying seems a good + * response to SIGINT. We'd use exit(), but that's not + * async-signal-safe, so we'll have to resort to _exit(). + * We use write() because it is async-signal-safe. */ + static const char message[] = + "Unable to write to quit pipe - buffer full?\n" + "Will exit instead.\n"; + + write (STDERR_FILENO, message, strlen (message)); + _exit (1); + } + break; + } +} + +static gboolean +quit_idle_cb (gpointer user_data) +{ + mcd_mission_abort (MCD_MISSION (mcd)); + return FALSE; } +static gboolean +quit_event_cb (GIOChannel *source, GIOCondition condition, gpointer data) +{ + g_idle_add_full (G_PRIORITY_LOW, quit_idle_cb, NULL, NULL); + return FALSE; +} + +static void +init_quit_pipe (void) +{ + int i; + GIOChannel *channel; + GError *error = NULL; + + if (!g_unix_open_pipe (quit_pipe, FD_CLOEXEC, &error)) + { + g_warning ("Failed to get a pipe: %s", error->message); + g_clear_error (&error); + return; + } + for (i = 0 ; i < 2 ; i++) + { + int val; + val = fcntl (quit_pipe[i], F_GETFL, 0); + if (val < 0) + { + g_warning ("Failed to get flags from file descriptor %d: %s", + quit_pipe[i], strerror (errno)); + continue; + } + val = fcntl (quit_pipe[i], F_SETFL, val | O_NONBLOCK); + if (val < 0) + { + g_warning ("Failed to set flags from file descriptor %d: %s", + quit_pipe[i], strerror (errno)); + continue; + } + } + channel = g_io_channel_unix_new (quit_pipe[QUIT_READ_END]); + g_io_add_watch (channel, G_IO_IN, quit_event_cb, NULL); +} +#endif + int #ifdef BUILD_AS_ANDROID_SERVICE telepathy_mission_control_main (int argc, char **argv) @@ -56,7 +147,10 @@ telepathy_mission_control_main (int argc, char **argv) main (int argc, char **argv) #endif { - McdService *mcd; +#ifdef G_OS_UNIX + struct sigaction act; + sigset_t empty_mask; +#endif g_type_init (); g_set_application_name ("Account manager"); @@ -80,11 +174,22 @@ main (int argc, char **argv) /* Listen for suicide notification */ g_signal_connect_after (mcd, "abort", G_CALLBACK (on_abort), mcd); + /* Set up signals */ +#ifdef G_OS_UNIX + init_quit_pipe (); + sigemptyset (&empty_mask); + act.sa_handler = signal_handler; + act.sa_mask = empty_mask; + act.sa_flags = 0; + sigaction (SIGINT, &act, NULL); +#endif + /* connect */ mcd_mission_connect (MCD_MISSION (mcd)); mcd_service_run (MCD_OBJECT (mcd)); + g_clear_object (&mcd); tp_clear_object (&debug_sender); return 0; diff --git a/src/mcd-service.c b/src/mcd-service.c index 89f54d1e..71e9dfc8 100644 --- a/src/mcd-service.c +++ b/src/mcd-service.c @@ -193,3 +193,9 @@ mcd_service_run (McdService * self) g_main_loop_run (self->main_loop); } +void +mcd_service_stop (McdService * self) +{ + if (self->main_loop != NULL) + g_main_loop_quit (self->main_loop); +} diff --git a/src/mcd-service.h b/src/mcd-service.h index b436cef2..3613aae1 100644 --- a/src/mcd-service.h +++ b/src/mcd-service.h @@ -69,5 +69,6 @@ GType mcd_service_get_type (void); McdService *mcd_service_new (void); void mcd_service_run (McdService * self); +void mcd_service_stop (McdService * self); #endif -- cgit v1.2.1