summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Zeuthen <davidz@redhat.com>2010-07-30 12:19:55 -0400
committerDavid Zeuthen <davidz@redhat.com>2010-07-30 12:19:55 -0400
commit4a9e4f72db4ec00500d9334f7411a086d7c81d0f (patch)
tree566f3f3d3f56f90538e48e97fb8bf039db523b37
parent2d0ef52d64707666fd8b6a85be50fa6e3e65ec9e (diff)
downloadpolkit-4a9e4f72db4ec00500d9334f7411a086d7c81d0f.tar.gz
Make polkitd accept --replace and gracefully handle SIGINT
E.g. actually clean up everything before exiting. This makes it much easier to chase memory leaks. Signed-off-by: David Zeuthen <davidz@redhat.com>
-rw-r--r--docs/polkit/polkit-1-sections.txt3
-rw-r--r--src/polkit/polkitauthorizationresult.c2
-rw-r--r--src/polkitbackend/polkitbackendauthority.c112
-rw-r--r--src/polkitbackend/polkitbackendauthority.h6
-rw-r--r--src/polkitd/Makefile.am3
-rw-r--r--src/polkitd/gposixsignal.c128
-rw-r--r--src/polkitd/gposixsignal.h42
-rw-r--r--src/polkitd/main.c135
8 files changed, 329 insertions, 102 deletions
diff --git a/docs/polkit/polkit-1-sections.txt b/docs/polkit/polkit-1-sections.txt
index 6b03fa2..999abb2 100644
--- a/docs/polkit/polkit-1-sections.txt
+++ b/docs/polkit/polkit-1-sections.txt
@@ -293,7 +293,8 @@ polkit_backend_authority_add_lockdown_for_action_finish
polkit_backend_authority_remove_lockdown_for_action
polkit_backend_authority_remove_lockdown_for_action_finish
polkit_backend_authority_get
-polkit_backend_register_authority
+polkit_backend_authority_register
+polkit_backend_authority_unregister
<SUBSECTION Standard>
POLKIT_BACKEND_AUTHORITY
POLKIT_BACKEND_IS_AUTHORITY
diff --git a/src/polkit/polkitauthorizationresult.c b/src/polkit/polkitauthorizationresult.c
index 85b039f..5bc1065 100644
--- a/src/polkit/polkitauthorizationresult.c
+++ b/src/polkit/polkitauthorizationresult.c
@@ -109,7 +109,7 @@ polkit_authorization_result_new (gboolean is_authorized,
authorization_result = POLKIT_AUTHORIZATION_RESULT (g_object_new (POLKIT_TYPE_AUTHORIZATION_RESULT, NULL));
authorization_result->is_authorized = is_authorized;
authorization_result->is_challenge = is_challenge;
- authorization_result->details = g_object_ref (details);
+ authorization_result->details = details != NULL ? g_object_ref (details) : NULL;
return authorization_result;
}
diff --git a/src/polkitbackend/polkitbackendauthority.c b/src/polkitbackend/polkitbackendauthority.c
index 4373315..33c800f 100644
--- a/src/polkitbackend/polkitbackendauthority.c
+++ b/src/polkitbackend/polkitbackendauthority.c
@@ -657,11 +657,10 @@ typedef struct
PolkitBackendAuthority *authority;
- GDBusConnection *system_bus;
+ GDBusConnection *connection;
gulong authority_changed_id;
- gchar *well_known_name;
gchar *object_path;
GHashTable *cancellation_id_to_check_auth_data;
@@ -670,21 +669,18 @@ typedef struct
static void
server_free (Server *server)
{
- g_free (server->well_known_name);
g_free (server->object_path);
- /* TODO: release well_known_name if not NULL */
-
//g_signal_handler_disconnect (server->bus, server->name_owner_changed_id);
if (server->authority_registration_id > 0)
- g_dbus_connection_unregister_object (server->system_bus, server->authority_registration_id);
+ g_dbus_connection_unregister_object (server->connection, server->authority_registration_id);
if (server->name_owner_changed_signal_id > 0)
- g_dbus_connection_signal_unsubscribe (server->system_bus, server->name_owner_changed_signal_id);
+ g_dbus_connection_signal_unsubscribe (server->connection, server->name_owner_changed_signal_id);
- if (server->system_bus != NULL)
- g_object_unref (server->system_bus);
+ if (server->connection != NULL)
+ g_object_unref (server->connection);
if (server->introspection_info != NULL)
g_dbus_node_info_unref (server->introspection_info);
@@ -695,6 +691,8 @@ server_free (Server *server)
if (server->cancellation_id_to_check_auth_data != NULL)
g_hash_table_unref (server->cancellation_id_to_check_auth_data);
+ g_object_unref (server->authority);
+
g_free (server);
}
@@ -706,7 +704,7 @@ on_authority_changed (PolkitBackendAuthority *authority,
GError *error;
error = NULL;
- if (!g_dbus_connection_emit_signal (server->system_bus,
+ if (!g_dbus_connection_emit_signal (server->connection,
NULL, /* destination bus name */
server->object_path,
"org.freedesktop.PolicyKit1.Authority",
@@ -719,14 +717,6 @@ on_authority_changed (PolkitBackendAuthority *authority,
}
}
-static void
-authority_died (gpointer user_data,
- GObject *where_the_object_was)
-{
- Server *server = user_data;
- server_free (server);
-}
-
static const gchar *server_introspection_data =
"<node>"
" <interface name='org.freedesktop.PolicyKit1.Authority'>"
@@ -1455,19 +1445,32 @@ static const GDBusInterfaceVTable server_vtable =
};
/**
- * polkit_backend_register_authority:
+ * polkit_backend_authority_unregister:
+ * @registration_id: A #gpointer obtained from polkit_backend_authority_register().
+ *
+ * Unregisters a #PolkitBackendAuthority registered with polkit_backend_authority_register().
+ */
+void
+polkit_backend_authority_unregister (gpointer registration_id)
+{
+ Server *server = registration_id;
+ server_free (server);
+}
+
+/**
+ * polkit_backend_authority_register:
+ * @connection: The #GDBusConnection to register the authority on.
* @authority: A #PolkitBackendAuthority.
- * @well_known_name: Well-known name to claim on the system bus or %NULL to not claim a well-known name.
* @object_path: Object path of the authority.
* @error: Return location for error.
*
- * Registers @authority on the system message bus.
+ * Registers @authority on a #GDBusConnection.
*
- * Returns: %TRUE if @authority was registered, %FALSE if @error is set.
- **/
-gboolean
-polkit_backend_register_authority (PolkitBackendAuthority *authority,
- const gchar *well_known_name,
+ * Returns: A #gpointer that can be used with polkit_backend_authority_unregister() or %NULL if @error is set.
+ */
+gpointer
+polkit_backend_authority_register (PolkitBackendAuthority *authority,
+ GDBusConnection *connection,
const gchar *object_path,
GError **error)
{
@@ -1477,18 +1480,14 @@ polkit_backend_register_authority (PolkitBackendAuthority *authority,
server->cancellation_id_to_check_auth_data = g_hash_table_new (g_str_hash, g_str_equal);
- server->system_bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error);
- if (server->system_bus == NULL)
- goto error;
-
- server->well_known_name = g_strdup (well_known_name);
+ server->connection = g_object_ref (connection);
server->object_path = g_strdup (object_path);
server->introspection_info = g_dbus_node_info_new_for_xml (server_introspection_data, error);
if (server->introspection_info == NULL)
goto error;
- server->authority_registration_id = g_dbus_connection_register_object (server->system_bus,
+ server->authority_registration_id = g_dbus_connection_register_object (server->connection,
object_path,
g_dbus_node_info_lookup_interface (server->introspection_info, "org.freedesktop.PolicyKit1.Authority"),
&server_vtable,
@@ -1500,46 +1499,8 @@ polkit_backend_register_authority (PolkitBackendAuthority *authority,
goto error;
}
- if (well_known_name != NULL)
- {
- GVariant *result;
- guint32 request_name_result;
-
- /* TODO: use g_bus_own_name() instead */
- result = g_dbus_connection_call_sync (server->system_bus,
- "org.freedesktop.DBus", /* name */
- "/org/freedesktop/DBus", /* path */
- "org.freedesktop.DBus", /* interface */
- "RequestName",
- g_variant_new ("(su)", well_known_name, 0),
- G_VARIANT_TYPE ("(u)"),
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- NULL, /* GCancellable */
- error);
- if (result == NULL)
- {
- g_prefix_error (error,
- "Could not become primary name owner for `%s'. RequestName() failed with: ",
- well_known_name);
- goto error;
- }
- g_variant_get (result, "(u)", &request_name_result);
- g_variant_unref (result);
- if (request_name_result != 1)
- {
- g_set_error (error,
- POLKIT_ERROR,
- POLKIT_ERROR_FAILED,
- "Could not become primary name owner for `%s'. RequestName returned %d",
- well_known_name,
- request_name_result);
- goto error;
- }
- }
-
server->name_owner_changed_signal_id =
- g_dbus_connection_signal_subscribe (server->system_bus,
+ g_dbus_connection_signal_subscribe (server->connection,
"org.freedesktop.DBus", /* sender */
"org.freedesktop.DBus", /* interface */
"NameOwnerChanged", /* member */
@@ -1550,21 +1511,18 @@ polkit_backend_register_authority (PolkitBackendAuthority *authority,
server,
NULL); /* GDestroyNotify */
- server->authority = authority;
+ server->authority = g_object_ref (authority);
server->authority_changed_id = g_signal_connect (server->authority,
"changed",
G_CALLBACK (on_authority_changed),
server);
- /* take a weak ref and kill server when listener dies */
- g_object_weak_ref (G_OBJECT (server->authority), authority_died, server);
-
- return TRUE;
+ return server;
error:
server_free (server);
- return FALSE;
+ return NULL;
}
diff --git a/src/polkitbackend/polkitbackendauthority.h b/src/polkitbackend/polkitbackendauthority.h
index 7ce5fde..626c4a5 100644
--- a/src/polkitbackend/polkitbackendauthority.h
+++ b/src/polkitbackend/polkitbackendauthority.h
@@ -329,11 +329,13 @@ gboolean polkit_backend_authority_remove_lockdown_for_action_finish (PolkitBacke
PolkitBackendAuthority *polkit_backend_authority_get (void);
-gboolean polkit_backend_register_authority (PolkitBackendAuthority *authority,
- const gchar *well_known_name,
+gpointer polkit_backend_authority_register (PolkitBackendAuthority *authority,
+ GDBusConnection *connection,
const gchar *object_path,
GError **error);
+void polkit_backend_authority_unregister (gpointer registration_id);
+
G_END_DECLS
#endif /* __POLKIT_BACKEND_AUTHORITY_H */
diff --git a/src/polkitd/Makefile.am b/src/polkitd/Makefile.am
index 1234417..5ea3e95 100644
--- a/src/polkitd/Makefile.am
+++ b/src/polkitd/Makefile.am
@@ -17,7 +17,8 @@ INCLUDES = \
libexec_PROGRAMS = polkitd
polkitd_SOURCES = \
- main.c \
+ main.c \
+ gposixsignal.h gposixsignal.c \
$(NULL)
polkitd_CFLAGS = \
diff --git a/src/polkitd/gposixsignal.c b/src/polkitd/gposixsignal.c
new file mode 100644
index 0000000..8e9bb65
--- /dev/null
+++ b/src/polkitd/gposixsignal.c
@@ -0,0 +1,128 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * 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/polkitd/gposixsignal.h b/src/polkitd/gposixsignal.h
new file mode 100644
index 0000000..f9b3249
--- /dev/null
+++ b/src/polkitd/gposixsignal.h
@@ -0,0 +1,42 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * 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__ */
diff --git a/src/polkitd/main.c b/src/polkitd/main.c
index ff39dd9..4b1967a 100644
--- a/src/polkitd/main.c
+++ b/src/polkitd/main.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Red Hat, Inc.
+ * Copyright (C) 2008-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
@@ -19,49 +19,144 @@
* Author: David Zeuthen <davidz@redhat.com>
*/
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
+#include "config.h"
+#include <signal.h>
#include <polkit/polkit.h>
#include <polkitbackend/polkitbackend.h>
-int
-main (int argc, char **argv)
+#include "gposixsignal.h"
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static PolkitBackendAuthority *authority = NULL;
+static gpointer registration_id = NULL;
+static GMainLoop *loop = NULL;
+static gboolean opt_replace = FALSE;
+static GOptionEntry opt_entries[] = {
+ {"replace", 0, 0, G_OPTION_ARG_NONE, &opt_replace, "Replace existing daemon", NULL},
+ {NULL }
+};
+
+static void
+on_bus_acquired (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
{
- int ret;
GError *error;
- GMainLoop *loop;
- PolkitBackendAuthority *authority;
-
- ret = 1;
- error = NULL;
- authority = NULL;
- g_type_init ();
+ g_print ("Connected to the system bus\n");
- loop = g_main_loop_new (NULL, FALSE);
+ g_assert (authority == NULL);
+ g_assert (registration_id == NULL);
authority = polkit_backend_authority_get ();
-
g_print ("Using authority class %s\n", g_type_name (G_TYPE_FROM_INSTANCE (authority)));
- if (!polkit_backend_register_authority (authority,
- "org.freedesktop.PolicyKit1",
- "/org/freedesktop/PolicyKit1/Authority",
- &error))
+ error = NULL;
+ registration_id = polkit_backend_authority_register (authority,
+ connection,
+ "/org/freedesktop/PolicyKit1/Authority",
+ &error);
+ if (registration_id == NULL)
{
g_printerr ("Error registering authority: %s\n", error->message);
g_error_free (error);
+ g_main_loop_quit (loop); /* exit */
+ }
+}
+
+static void
+on_name_lost (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ g_print ("Lost the name org.freedesktop.PolicyKit1 - exiting\n");
+ g_main_loop_quit (loop);
+}
+
+static void
+on_name_acquired (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ g_print ("Acquired the name org.freedesktop.PolicyKit1\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)
+{
+ GError *error;
+ GOptionContext *opt_context;
+ gint ret;
+ guint name_owner_id;
+ guint sigint_id;
+
+ ret = 1;
+ loop = NULL;
+ opt_context = NULL;
+ name_owner_id = 0;
+ sigint_id = 0;
+ registration_id = NULL;
+
+ g_type_init ();
+
+ opt_context = g_option_context_new ("polkit authority");
+ g_option_context_add_main_entries (opt_context, opt_entries, NULL);
+ error = NULL;
+ if (!g_option_context_parse (opt_context, &argc, &argv, &error))
+ {
+ g_printerr ("Error parsing options: %s", error->message);
+ g_error_free (error);
goto out;
}
+ 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.PolicyKit1",
+ G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
+ (opt_replace ? G_BUS_NAME_OWNER_FLAGS_REPLACE : 0),
+ on_bus_acquired,
+ on_name_acquired,
+ on_name_lost,
+ NULL,
+ NULL);
+
+ g_print ("Entering main event loop\n");
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 (registration_id != NULL)
+ polkit_backend_authority_unregister (registration_id);
if (authority != NULL)
g_object_unref (authority);
+ if (loop != NULL)
+ 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;
}