PolicyKit: Branch 'gdbus'

David Zeuthen david at kemper.freedesktop.org
Fri Jul 30 09:20:44 PDT 2010


 docs/polkit/polkit-1-sections.txt          |    3 
 src/polkit/polkitauthorizationresult.c     |    2 
 src/polkitbackend/polkitbackendauthority.c |  112 +++++++-----------------
 src/polkitbackend/polkitbackendauthority.h |    6 -
 src/polkitd/Makefile.am                    |    3 
 src/polkitd/gposixsignal.c                 |  128 +++++++++++++++++++++++++++
 src/polkitd/gposixsignal.h                 |   42 +++++++++
 src/polkitd/main.c                         |  135 ++++++++++++++++++++++++-----
 8 files changed, 329 insertions(+), 102 deletions(-)

New commits:
commit 4a9e4f72db4ec00500d9334f7411a086d7c81d0f
Author: David Zeuthen <davidz at redhat.com>
Date:   Fri Jul 30 12:19:55 2010 -0400

    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 at redhat.com>

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 at 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 at 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 at 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;
 }


More information about the hal-commit mailing list