system-settings: fix shutdown issues

Shutdown on SIGTERM, and don't segfault when quitting cleanly.  Can't
send signals on an object that's being disposed of, so don't do that.
Fix a memory leak of the Hal manager's priv->devices on shutdown, not
that it matters.
This commit is contained in:
Dan Williams 2009-02-17 10:42:25 -05:00
parent f33b7627fe
commit f90d079858
2 changed files with 69 additions and 34 deletions

View file

@ -28,6 +28,7 @@
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/ether.h>
#include <signal.h>
#include <glib.h>
#include <glib/gi18n.h>
@ -49,6 +50,9 @@
#include "nm-system-config-hal-manager.h"
#include "nm-system-config-interface.h"
static GMainLoop *loop = NULL;
static gboolean debug = FALSE;
typedef struct {
DBusConnection *connection;
DBusGConnection *g_connection;
@ -57,13 +61,13 @@ typedef struct {
NMSystemConfigHalManager *hal_mgr;
NMSysconfigSettings *settings;
GMainLoop *loop;
GHashTable *wired_devices;
} Application;
NMSystemConfigHalManager *nm_system_config_hal_manager_get (DBusGConnection *g_connection);
void nm_system_config_hal_manager_shutdown (NMSystemConfigHalManager *self);
static gboolean dbus_init (Application *app);
static gboolean start_dbus_service (Application *app);
@ -194,7 +198,7 @@ load_stuff (gpointer user_data)
g_slist_free (devs);
if (!start_dbus_service (app)) {
g_main_loop_quit (app->loop);
g_main_loop_quit (loop);
return FALSE;
}
@ -461,11 +465,9 @@ dbus_cleanup (Application *app)
static void
destroy_cb (DBusGProxy *proxy, gpointer user_data)
{
Application *app = (Application *) user_data;
/* Clean up existing connection */
g_warning ("disconnected from the system bus, exiting.");
g_main_loop_quit (app->loop);
g_main_loop_quit (loop);
}
static gboolean
@ -608,6 +610,30 @@ logging_shutdown (void)
closelog ();
}
static void
signal_handler (int signo)
{
if (signo == SIGINT || signo == SIGTERM) {
if (debug)
g_message ("Caught signal %d, shutting down...", signo);
g_main_loop_quit (loop);
}
}
static void
setup_signals (void)
{
struct sigaction action;
sigset_t mask;
sigemptyset (&mask);
action.sa_handler = signal_handler;
action.sa_mask = mask;
action.sa_flags = 0;
sigaction (SIGTERM, &action, NULL);
sigaction (SIGINT, &action, NULL);
}
int
main (int argc, char **argv)
{
@ -616,7 +642,6 @@ main (int argc, char **argv)
GError *error = NULL;
char *plugins = NULL;
char *config = NULL;
gboolean debug = FALSE;
GOptionEntry entries[] = {
{ "config", 0, 0, G_OPTION_ARG_FILENAME, &config, "Config file location", "/path/to/config.file" },
@ -656,7 +681,7 @@ main (int argc, char **argv)
return 1;
}
app->loop = g_main_loop_new (NULL, FALSE);
loop = g_main_loop_new (NULL, FALSE);
if (!debug)
logging_setup ();
@ -682,15 +707,18 @@ main (int argc, char **argv)
}
g_free (plugins);
setup_signals ();
g_idle_add (load_stuff, app);
g_main_loop_run (app->loop);
g_main_loop_run (loop);
g_object_unref (app->settings);
nm_system_config_hal_manager_shutdown (app->hal_mgr);
g_object_unref (app->hal_mgr);
g_hash_table_destroy (app->wired_devices);
g_object_unref (app->settings);
dbus_cleanup (app);
if (!debug)

View file

@ -30,6 +30,8 @@
NMSystemConfigHalManager *nm_system_config_hal_manager_get (DBusGConnection *g_connection);
void nm_system_config_hal_manager_shutdown (NMSystemConfigHalManager *self);
#define NUM_DEVICE_TYPES NM_DEVICE_TYPE_CDMA
typedef struct {
@ -221,30 +223,6 @@ init_dbus (NMSystemConfigHalManager *manager, DBusGConnection *g_connection)
return TRUE;
}
static void
remove_all_devices (gpointer key, gpointer data, gpointer user_data)
{
NMSystemConfigHalManager *manager = NM_SYSTEM_CONFIG_HAL_MANAGER (user_data);
g_signal_emit (manager, signals[DEVICE_REMOVED], 0, key, GPOINTER_TO_UINT (data));
}
static void
cleanup_dbus (NMSystemConfigHalManager *manager)
{
NMSystemConfigHalManagerPrivate *priv = NM_SYSTEM_CONFIG_HAL_MANAGER_GET_PRIVATE (manager);
g_hash_table_foreach (priv->devices, (GHFunc) remove_all_devices, manager);
g_hash_table_remove_all (priv->devices);
if (priv->proxy) {
g_object_unref (priv->proxy);
priv->proxy = NULL;
}
priv->g_connection = NULL;
}
static NMSystemConfigHalManager *
nm_system_config_hal_manager_new (DBusGConnection *g_connection)
{
@ -283,10 +261,39 @@ nm_system_config_hal_manager_init (NMSystemConfigHalManager *manager)
priv->devices = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
}
static void
signal_removed (gpointer key, gpointer data, gpointer user_data)
{
NMSystemConfigHalManager *manager = NM_SYSTEM_CONFIG_HAL_MANAGER (user_data);
g_signal_emit (manager, signals[DEVICE_REMOVED], 0, key, GPOINTER_TO_UINT (data));
}
void
nm_system_config_hal_manager_shutdown (NMSystemConfigHalManager *self)
{
NMSystemConfigHalManagerPrivate *priv = NM_SYSTEM_CONFIG_HAL_MANAGER_GET_PRIVATE (self);
g_hash_table_foreach (priv->devices, (GHFunc) signal_removed, self);
g_hash_table_remove_all (priv->devices);
}
static void
dispose (GObject *object)
{
cleanup_dbus (NM_SYSTEM_CONFIG_HAL_MANAGER (object));
NMSystemConfigHalManagerPrivate *priv = NM_SYSTEM_CONFIG_HAL_MANAGER_GET_PRIVATE (object);
if (priv->devices) {
g_hash_table_remove_all (priv->devices);
g_hash_table_destroy (priv->devices);
}
if (priv->proxy) {
g_object_unref (priv->proxy);
priv->proxy = NULL;
}
priv->g_connection = NULL;
G_OBJECT_CLASS (nm_system_config_hal_manager_parent_class)->dispose (object);
}