Do proper shutdown upon receiving SIGINT
authorDavid Zeuthen <davidz@redhat.com>
Tue, 8 Jun 2010 22:21:36 +0000 (18:21 -0400)
committerDavid Zeuthen <davidz@redhat.com>
Tue, 8 Jun 2010 22:21:36 +0000 (18:21 -0400)
This helps with finding/detecting memory leaks.

src/Makefile.am
src/gposixsignal.c [new file with mode: 0644]
src/gposixsignal.h [new file with mode: 0644]
src/main.c

index 6b54b5b..5c42653 100644 (file)
@@ -49,6 +49,7 @@ udisks_daemon_SOURCES =                                               \
        linuxdevice.h                   linuxdevice.c                   \
        private.h                                                       \
        profile.h                                                       \
+       gposixsignal.h                  gposixsignal.c                  \
        $(BUILT_SOURCES)                                                \
        $(NULL)
 
diff --git a/src/gposixsignal.c b/src/gposixsignal.c
new file mode 100644 (file)
index 0000000..2b99d88
--- /dev/null
@@ -0,0 +1,129 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* GDBus - GLib D-Bus Library
+ *
+ * Copyright (C) 2010 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#include "config.h"
+
+#include <unistd.h>
+#include <sys/signalfd.h>
+#include <signal.h>
+
+#include "gposixsignal.h"
+
+typedef struct
+{
+  GSource source;
+  GPollFD pollfd;
+  gint signum;
+} _GPosixSignalSource;
+
+static gboolean
+_g_posix_signal_source_prepare (GSource  *_source,
+                                gint     *timeout)
+{
+  *timeout = -1;
+  return FALSE;
+}
+
+static gboolean
+_g_posix_signal_source_check (GSource  *_source)
+{
+  _GPosixSignalSource *source = (_GPosixSignalSource *) _source;
+  return source->pollfd.revents != 0;
+}
+
+static gboolean
+_g_posix_signal_source_dispatch (GSource     *_source,
+                                 GSourceFunc  callback,
+                                 gpointer     user_data)
+
+{
+  _GPosixSignalWatchFunc func = (_GPosixSignalWatchFunc) callback;
+  g_warn_if_fail (func != NULL);
+  return (*func) (user_data);
+}
+
+static void
+_g_posix_signal_source_finalize (GSource *_source)
+{
+  _GPosixSignalSource *source = (_GPosixSignalSource *) _source;
+  close (source->pollfd.fd);
+}
+
+static GSourceFuncs _g_posix_signal_source_funcs =
+{
+  _g_posix_signal_source_prepare,
+  _g_posix_signal_source_check,
+  _g_posix_signal_source_dispatch,
+  _g_posix_signal_source_finalize
+};
+
+GSource *
+_g_posix_signal_source_new (gint signum)
+{
+  sigset_t sigset;
+  gint fd;
+  GSource *_source;
+  _GPosixSignalSource *source;
+
+  _source = NULL;
+
+  sigemptyset (&sigset);
+  sigaddset (&sigset, signum);
+
+  if (sigprocmask (SIG_BLOCK, &sigset, NULL) == -1)
+    g_assert_not_reached ();
+
+  fd = signalfd (-1, &sigset, SFD_NONBLOCK | SFD_CLOEXEC);
+
+  _source = g_source_new (&_g_posix_signal_source_funcs, sizeof (_GPosixSignalSource));
+  source = (_GPosixSignalSource *) _source;
+
+  source->pollfd.fd = fd;
+  source->pollfd.events = G_IO_IN;
+  g_source_add_poll (_source, &source->pollfd);
+
+  source->signum = signum;
+  return _source;
+}
+
+guint
+_g_posix_signal_watch_add (gint                   signum,
+                           gint                   priority,
+                           _GPosixSignalWatchFunc function,
+                           gpointer               user_data,
+                           GDestroyNotify         notify)
+{
+  GSource *source;
+  guint id;
+
+  g_return_val_if_fail (function != NULL, 0);
+
+  source = _g_posix_signal_source_new (signum);
+  if (priority != G_PRIORITY_DEFAULT_IDLE)
+    g_source_set_priority (source, priority);
+  g_source_set_callback (source, (GSourceFunc) function, user_data, notify);
+  id = g_source_attach (source, NULL);
+  g_source_unref (source);
+
+  return id;
+}
diff --git a/src/gposixsignal.h b/src/gposixsignal.h
new file mode 100644 (file)
index 0000000..7c6d6e6
--- /dev/null
@@ -0,0 +1,43 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* GDBus - GLib D-Bus Library
+ *
+ * Copyright (C) 2010 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#ifndef ___G_POSIX_SIGNAL_H__
+#define ___G_POSIX_SIGNAL_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef gboolean (*_GPosixSignalWatchFunc) (gpointer user_data);
+
+GSource *_g_posix_signal_source_new (gint signum);
+
+guint _g_posix_signal_watch_add (gint                   signum,
+                                 gint                   priority,
+                                 _GPosixSignalWatchFunc function,
+                                 gpointer               user_data,
+                                 GDestroyNotify         notify);
+
+G_END_DECLS
+
+#endif /* ___G_POSIX_SIGNAL_H__ */
index 857c3ce..e40c560 100644 (file)
 
 #include "config.h"
 
+#include <signal.h>
+
 #include <gio/gio.h>
 
 #include "profile.h"
-
 #include "linuxdaemon.h"
+#include "gposixsignal.h"
+
+/* ---------------------------------------------------------------------------------------------------- */
 
 static Daemon *the_daemon = NULL;
 static GMainLoop *loop = NULL;
@@ -84,6 +88,14 @@ on_name_acquired (GDBusConnection *connection,
   g_print ("Acquired the name org.freedesktop.UDisks on the system bus\n");
 }
 
+static gboolean
+on_sigint (gpointer user_data)
+{
+  g_print ("Handling SIGINT\n");
+  g_main_loop_quit (loop);
+  return FALSE;
+}
+
 int
 main (int    argc,
       char **argv)
@@ -93,6 +105,7 @@ main (int    argc,
   gchar *s;
   gint ret;
   guint name_owner_id;
+  guint sigint_id;
 
   PROFILE ("main(): start");
 
@@ -100,6 +113,7 @@ main (int    argc,
   loop = NULL;
   opt_context = NULL;
   name_owner_id = 0;
+  sigint_id = 0;
 
   g_type_init ();
 
@@ -140,6 +154,14 @@ main (int    argc,
     }
   g_free (s);
 
+  loop = g_main_loop_new (NULL, FALSE);
+
+  sigint_id = _g_posix_signal_watch_add (SIGINT,
+                                         G_PRIORITY_DEFAULT,
+                                         on_sigint,
+                                         NULL,
+                                         NULL);
+
   name_owner_id = g_bus_own_name (G_BUS_TYPE_SYSTEM,
                                   "org.freedesktop.UDisks",
                                   G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
@@ -150,15 +172,17 @@ main (int    argc,
                                   NULL,
                                   NULL);
 
-  PROFILE ("main(): starting main loop");
-
-  loop = g_main_loop_new (NULL, FALSE);
+  g_print ("Entering main event loop\n");
 
+  PROFILE ("main(): starting main loop");
   g_main_loop_run (loop);
 
   ret = 0;
 
+  g_print ("Shutting down\n");
  out:
+  if (sigint_id > 0)
+    g_source_remove (sigint_id);
   if (name_owner_id != 0)
     g_bus_unown_name (name_owner_id);
   if (the_daemon != NULL)
@@ -167,5 +191,7 @@ main (int    argc,
     g_main_loop_unref (loop);
   if (opt_context != NULL)
     g_option_context_free (opt_context);
+
+  g_print ("Exiting with code %d\n", ret);
   return ret;
 }