diff options
author | Alban Crequy <alban.crequy@collabora.co.uk> | 2012-03-16 15:32:51 +0000 |
---|---|---|
committer | Alban Crequy <alban.crequy@collabora.co.uk> | 2012-03-26 13:57:06 +0100 |
commit | 853fefbb9663a5d6003cdefbc16c19c67d5bfcc7 (patch) | |
tree | 6f2d8809a4cd3cbb97a762f263c5fcda7e9adf79 | |
parent | 72498e161d71b6751d825888a684f62c304a9434 (diff) | |
download | telepathy-mission-control-853fefbb9663a5d6003cdefbc16c19c67d5bfcc7.tar.gz |
Add mcd_service_stop() and stop the McdService when SIGINT is sent
https://bugs.freedesktop.org/show_bug.cgi?id=47054
-rw-r--r-- | server/mc-server.c | 115 | ||||
-rw-r--r-- | src/mcd-service.c | 6 | ||||
-rw-r--r-- | 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 <unistd.h> #include <glib.h> +#ifdef G_OS_UNIX +#include <glib-unix.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <errno.h> +#include <string.h> +#include <signal.h> +#endif + #include <telepathy-glib/telepathy-glib.h> #include <telepathy-glib/debug-sender.h> #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 |