summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlban Crequy <alban.crequy@collabora.co.uk>2012-03-16 15:32:51 +0000
committerAlban Crequy <alban.crequy@collabora.co.uk>2012-03-26 13:57:06 +0100
commit853fefbb9663a5d6003cdefbc16c19c67d5bfcc7 (patch)
tree6f2d8809a4cd3cbb97a762f263c5fcda7e9adf79
parent72498e161d71b6751d825888a684f62c304a9434 (diff)
downloadtelepathy-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.c115
-rw-r--r--src/mcd-service.c6
-rw-r--r--src/mcd-service.h1
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