[Xfce4-commits] <tumbler:master> Fix ownership race conditions when started twice (bug #8001).

Jannis Pohlmann noreply at xfce.org
Wed Sep 28 23:16:01 CEST 2011


Updating branch refs/heads/master
         to 776070012e3d5d2bff5a1b2a9e175ced7122f125 (commit)
       from aab140d868c1ebedbb04bbd65deddf94dc21787b (commit)

commit 776070012e3d5d2bff5a1b2a9e175ced7122f125
Author: Jannis Pohlmann <jannis at xfce.org>
Date:   Wed Sep 28 23:11:57 2011 +0200

    Fix ownership race conditions when started twice (bug #8001).
    
    It can happen that D-Bus activates tumblerd multiple times if the
    activated instance doesn't bring up the service quickly enough. We need
    to detect this in order to exit duplicate instances gracefully (exit
    code 0). Exiting with an error code breaks clients.
    
    For more information, see the following bugs:
    
      https://bugzilla.xfce.org/show_bug.cgi?id=8001
      https://bugs.freedesktop.org/show_bug.cgi?id=41233

 NEWS                             |    1 +
 tumblerd/main.c                  |   79 +++++++++++++++++++++++++-------------
 tumblerd/tumbler-cache-service.c |   32 ++++++++++-----
 tumblerd/tumbler-manager.c       |   44 ++++++++++++++++-----
 tumblerd/tumbler-service.c       |   32 ++++++++++-----
 5 files changed, 131 insertions(+), 57 deletions(-)

diff --git a/NEWS b/NEWS
index 48e3896..c93ec82 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,7 @@
 0.1.xx
 ======
 - Fix generation of video images by starting the pipeline (bug #7996).
+- Fix ownership race conditions when started twice (bug #8001).
 
 0.1.22
 ======
diff --git a/tumblerd/main.c b/tumblerd/main.c
index f2de4f0..f79049b 100644
--- a/tumblerd/main.c
+++ b/tumblerd/main.c
@@ -65,6 +65,7 @@ main (int    argc,
   TumblerService          *service;
   TumblerCacheService     *cache_service;
   GMainLoop               *main_loop;
+  gboolean                 already_running = FALSE;
   GError                  *error = NULL;
   GList                   *providers;
   GList                   *thumbnailers;
@@ -99,22 +100,6 @@ main (int    argc,
   /* create the lifecycle manager */
   lifecycle_manager = tumbler_lifecycle_manager_new ();
 
-  /* create the thumbnail cache service */
-  cache_service = tumbler_cache_service_new (connection, lifecycle_manager);
-
-  /* try to start the service and exit if that fails */
-  if (!tumbler_cache_service_start (cache_service, &error))
-    {
-      g_warning (_("Failed to start the thumbnail cache service: %s"), error->message);
-      g_error_free (error);
-
-      g_object_unref (cache_service);
-
-      dbus_g_connection_unref (connection);
-
-      return EXIT_FAILURE;
-    }
-
   /* create the thumbnailer registry */
   registry = tumbler_registry_new ();
 
@@ -152,6 +137,15 @@ main (int    argc,
   /* update the URI schemes / MIME types supported information */
   tumbler_registry_update_supported (registry);
 
+  /* create the thumbnail cache service */
+  cache_service = tumbler_cache_service_new (connection, lifecycle_manager);
+
+  /* create the thumbnailer manager service */
+  manager = tumbler_manager_new (connection, lifecycle_manager, registry);
+
+  /* create the generic thumbnailer service */
+  service = tumbler_service_new (connection, lifecycle_manager, registry);
+
   /* try to load specialized thumbnailers and exit if that fails */
   if (!tumbler_registry_load (registry, &error))
     {
@@ -159,49 +153,80 @@ main (int    argc,
                  error->message);
       g_error_free (error);
 
-      g_object_unref (registry);
+      g_object_unref (service);
+      g_object_unref (manager);
       g_object_unref (cache_service);
+      g_object_unref (registry);
 
       dbus_g_connection_unref (connection);
 
       return EXIT_FAILURE;
     }
 
-  /* create the thumbnailer manager service */
-  manager = tumbler_manager_new (connection, lifecycle_manager, registry);
+  /* try to start the service and exit if that fails */
+  if (!tumbler_cache_service_start (cache_service, &error))
+    {
+      if (error->domain == DBUS_GERROR && error->code == DBUS_GERROR_ADDRESS_IN_USE)
+        already_running = TRUE;
+
+      g_warning (_("Failed to start the thumbnail cache service: %s"), error->message);
+      g_error_free (error);
+
+      g_object_unref (service);
+      g_object_unref (manager);
+      g_object_unref (cache_service);
+      g_object_unref (registry);
+
+      dbus_g_connection_unref (connection);
+
+      if (already_running)
+        return EXIT_SUCCESS;
+      else
+        return EXIT_FAILURE;
+    }
 
   /* try to start the service and exit if that fails */
   if (!tumbler_manager_start (manager, &error))
     {
+      if (error->domain == DBUS_GERROR && error->code == DBUS_GERROR_ADDRESS_IN_USE)
+        already_running = TRUE;
+
       g_warning (_("Failed to start the thumbnailer manager: %s"), error->message);
       g_error_free (error);
 
+      g_object_unref (service);
       g_object_unref (manager);
-      g_object_unref (registry);
       g_object_unref (cache_service);
+      g_object_unref (registry);
 
       dbus_g_connection_unref (connection);
 
-      return EXIT_FAILURE;
+      if (already_running)
+        return EXIT_SUCCESS;
+      else
+        return EXIT_FAILURE;
     }
 
-  /* create the generic thumbnailer service */
-  service = tumbler_service_new (connection, lifecycle_manager, registry);
-
   /* try to start the service and exit if that fails */
   if (!tumbler_service_start (service, &error))
     {
+      if (error->domain == DBUS_GERROR && error->code == DBUS_GERROR_ADDRESS_IN_USE)
+        already_running = TRUE;
+
       g_warning (_("Failed to start the thumbnailer service: %s"), error->message);
       g_error_free (error);
 
       g_object_unref (service);
       g_object_unref (manager);
-      g_object_unref (registry);
       g_object_unref (cache_service);
+      g_object_unref (registry);
 
       dbus_g_connection_unref (connection);
 
-      return EXIT_FAILURE;
+      if (already_running)
+        return EXIT_SUCCESS;
+      else
+        return EXIT_FAILURE;
     }
 
   /* create a new main loop */
@@ -220,8 +245,8 @@ main (int    argc,
   /* shut our services down and release all objects */
   g_object_unref (service);
   g_object_unref (manager);
-  g_object_unref (registry);
   g_object_unref (cache_service);
+  g_object_unref (registry);
   g_object_unref (lifecycle_manager);
 
   /* disconnect from the D-Bus session bus */
diff --git a/tumblerd/tumbler-cache-service.c b/tumblerd/tumbler-cache-service.c
index f13177c..f6b2dc5 100644
--- a/tumblerd/tumbler-cache-service.c
+++ b/tumblerd/tumbler-cache-service.c
@@ -174,6 +174,15 @@ tumbler_cache_service_constructed (GObject *object)
                                             service, 1, FALSE, NULL);
   service->cleanup_pool = g_thread_pool_new (tumbler_cache_service_cleanup_thread, 
                                              service, 1, FALSE, NULL);
+
+  /* everything's fine, install the cache type D-Bus info */
+  dbus_g_object_type_install_info (G_OBJECT_TYPE (service),
+                                   &dbus_glib_tumbler_cache_service_object_info);
+
+  /* register the cache instance as a handler of the cache interface */
+  dbus_g_connection_register_g_object (service->connection, 
+                                       "/org/freedesktop/thumbnails/Cache1",
+                                       G_OBJECT (service));
 }
 
 
@@ -400,7 +409,19 @@ tumbler_cache_service_start (TumblerCacheService *service,
                                   DBUS_NAME_FLAG_DO_NOT_QUEUE, &dbus_error);
 
   /* check if that failed */
-  if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
+  if (result == DBUS_REQUEST_NAME_REPLY_EXISTS)
+    {
+      if (error != NULL)
+        {
+          g_set_error (error, DBUS_GERROR, DBUS_GERROR_ADDRESS_IN_USE,
+                       _("Another thumbnail cache service is already running"));
+        }
+
+      g_mutex_unlock (service->mutex);
+
+      return FALSE;
+    }
+  else if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
     {
       /* propagate the D-Bus error */
       if (dbus_error_is_set (&dbus_error))
@@ -421,15 +442,6 @@ tumbler_cache_service_start (TumblerCacheService *service,
       return FALSE;
     }
   
-  /* everything's fine, install the cache type D-Bus info */
-  dbus_g_object_type_install_info (G_OBJECT_TYPE (service),
-                                   &dbus_glib_tumbler_cache_service_object_info);
-
-  /* register the cache instance as a handler of the cache interface */
-  dbus_g_connection_register_g_object (service->connection, 
-                                       "/org/freedesktop/thumbnails/Cache1",
-                                       G_OBJECT (service));
-
   g_mutex_unlock (service->mutex);
 
   return TRUE;
diff --git a/tumblerd/tumbler-manager.c b/tumblerd/tumbler-manager.c
index 73e6778..feb2943 100644
--- a/tumblerd/tumbler-manager.c
+++ b/tumblerd/tumbler-manager.c
@@ -63,6 +63,7 @@ typedef struct _ThumbnailerInfo ThumbnailerInfo;
 
 
 
+static void             tumbler_manager_constructed       (GObject          *object);
 static void             tumbler_manager_finalize          (GObject          *object);
 static void             tumbler_manager_get_property      (GObject          *object,
                                                            guint             prop_id,
@@ -158,6 +159,7 @@ tumbler_manager_class_init (TumblerManagerClass *klass)
   GObjectClass *gobject_class;
 
   gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->constructed = tumbler_manager_constructed;
   gobject_class->finalize = tumbler_manager_finalize; 
   gobject_class->get_property = tumbler_manager_get_property;
   gobject_class->set_property = tumbler_manager_set_property;
@@ -198,6 +200,25 @@ tumbler_manager_init (TumblerManager *manager)
 
 
 
+
+
+static void
+tumbler_manager_constructed (GObject *object)
+{
+  TumblerManager *manager = TUMBLER_MANAGER (object);
+
+  /* everything's fine, install the manager type D-Bus info */
+  dbus_g_object_type_install_info (G_OBJECT_TYPE (manager), 
+                                   &dbus_glib_tumbler_manager_object_info);
+
+  /* register the manager instance as a handler of the manager interface */
+  dbus_g_connection_register_g_object (manager->connection, 
+                                       "/org/freedesktop/thumbnails/Manager1", 
+                                       G_OBJECT (manager));
+}
+
+
+
 static void
 tumbler_manager_finalize (GObject *object)
 {
@@ -1838,7 +1859,19 @@ tumbler_manager_start (TumblerManager *manager,
                                   DBUS_NAME_FLAG_DO_NOT_QUEUE, &dbus_error);
 
   /* check if that failed */
-  if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
+  if (result == DBUS_REQUEST_NAME_REPLY_EXISTS)
+    {
+      if (error != NULL)
+        {
+          g_set_error (error, DBUS_GERROR, DBUS_GERROR_ADDRESS_IN_USE,
+                       _("Another thumbnail cache service is already running"));
+        }
+
+      g_mutex_unlock (manager->mutex);
+
+      return FALSE;
+    }
+  else if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
     {
       /* propagate the D-Bus error */
       if (dbus_error_is_set (&dbus_error))
@@ -1860,15 +1893,6 @@ tumbler_manager_start (TumblerManager *manager,
       return FALSE;
     }
 
-  /* everything's fine, install the manager type D-Bus info */
-  dbus_g_object_type_install_info (G_OBJECT_TYPE (manager), 
-                                   &dbus_glib_tumbler_manager_object_info);
-
-  /* register the manager instance as a handler of the manager interface */
-  dbus_g_connection_register_g_object (manager->connection, 
-                                       "/org/freedesktop/thumbnails/Manager1", 
-                                       G_OBJECT (manager));
-
   g_mutex_unlock (manager->mutex);
 
   /* load thumbnailers installed into the system permanently */
diff --git a/tumblerd/tumbler-service.c b/tumblerd/tumbler-service.c
index 92ab7ac..8214a45 100644
--- a/tumblerd/tumbler-service.c
+++ b/tumblerd/tumbler-service.c
@@ -295,6 +295,15 @@ tumbler_service_constructed (GObject *object)
   scheduler = tumbler_group_scheduler_new ("background");
   tumbler_service_add_scheduler (service, scheduler);
   g_object_unref (scheduler);
+
+  /* everything is fine, install the generic thumbnailer D-Bus info */
+  dbus_g_object_type_install_info (G_OBJECT_TYPE (service),
+                                   &dbus_glib_tumbler_service_object_info);
+
+  /* register the service instance as a handler of this interface */
+  dbus_g_connection_register_g_object (service->connection, 
+                                       THUMBNAILER_PATH, 
+                                       G_OBJECT (service));
 }
 
 
@@ -744,7 +753,19 @@ tumbler_service_start (TumblerService *service,
                                   DBUS_NAME_FLAG_DO_NOT_QUEUE, &dbus_error);
 
   /* check if that failed */
-  if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
+  if (result == DBUS_REQUEST_NAME_REPLY_EXISTS)
+    {
+      if (error != NULL)
+        {
+          g_set_error (error, DBUS_GERROR, DBUS_GERROR_ADDRESS_IN_USE,
+                       _("Another thumbnail cache service is already running"));
+        }
+
+      g_mutex_unlock (service->mutex);
+
+      return FALSE;
+    }
+  else if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
     {
       /* propagate the D-Bus error */
       if (dbus_error_is_set (&dbus_error))
@@ -765,15 +786,6 @@ tumbler_service_start (TumblerService *service,
       return FALSE;
     }
 
-  /* everything is fine, install the generic thumbnailer D-Bus info */
-  dbus_g_object_type_install_info (G_OBJECT_TYPE (service),
-                                   &dbus_glib_tumbler_service_object_info);
-
-  /* register the service instance as a handler of this interface */
-  dbus_g_connection_register_g_object (service->connection, 
-                                       THUMBNAILER_PATH, 
-                                       G_OBJECT (service));
-
   g_mutex_unlock (service->mutex);
 
   return TRUE;


More information about the Xfce4-commits mailing list