From ee6a79a178f85a601671f76f658e6b2026ad6015 Mon Sep 17 00:00:00 2001 From: David Zeuthen Date: Tue, 8 Jun 2010 18:21:36 -0400 Subject: [PATCH] Do proper shutdown upon receiving SIGINT This helps with finding/detecting memory leaks. --- src/Makefile.am | 1 + src/gposixsignal.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/gposixsignal.h | 43 ++++++++++++++++++ src/main.c | 34 ++++++++++++-- 4 files changed, 203 insertions(+), 4 deletions(-) create mode 100644 src/gposixsignal.c create mode 100644 src/gposixsignal.h diff --git a/src/Makefile.am b/src/Makefile.am index 6b54b5b..5c42653 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 index 0000000..2b99d88 --- /dev/null +++ b/src/gposixsignal.c @@ -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 + */ + +#include "config.h" + +#include +#include +#include + +#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 index 0000000..7c6d6e6 --- /dev/null +++ b/src/gposixsignal.h @@ -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 + */ + +#ifndef ___G_POSIX_SIGNAL_H__ +#define ___G_POSIX_SIGNAL_H__ + +#include + +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__ */ diff --git a/src/main.c b/src/main.c index 857c3ce..e40c560 100644 --- a/src/main.c +++ b/src/main.c @@ -20,11 +20,15 @@ #include "config.h" +#include + #include #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; } -- 2.7.4