Sophie

Sophie

distrib > Fedora > 16 > x86_64 > media > os-src > by-pkgid > e630956ebd92edea9a6089dc5eb86111 > files > 1

tumbler-0.1.22-4.fc16.src.rpm

From 776070012e3d5d2bff5a1b2a9e175ced7122f125 Mon Sep 17 00:00:00 2001
From: Jannis Pohlmann <jannis@xfce.org>
Date: Wed, 28 Sep 2011 21:11:57 +0000
Subject: 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
---
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;
--
cgit