|
|
3655499 |
From 776070012e3d5d2bff5a1b2a9e175ced7122f125 Mon Sep 17 00:00:00 2001
|
|
|
3655499 |
From: Jannis Pohlmann <jannis@xfce.org>
|
|
|
3655499 |
Date: Wed, 28 Sep 2011 21:11:57 +0000
|
|
|
3655499 |
Subject: Fix ownership race conditions when started twice (bug #8001).
|
|
|
3655499 |
|
|
|
3655499 |
It can happen that D-Bus activates tumblerd multiple times if the
|
|
|
3655499 |
activated instance doesn't bring up the service quickly enough. We need
|
|
|
3655499 |
to detect this in order to exit duplicate instances gracefully (exit
|
|
|
3655499 |
code 0). Exiting with an error code breaks clients.
|
|
|
3655499 |
|
|
|
3655499 |
For more information, see the following bugs:
|
|
|
3655499 |
|
|
|
3655499 |
https://bugzilla.xfce.org/show_bug.cgi?id=8001
|
|
|
3655499 |
https://bugs.freedesktop.org/show_bug.cgi?id=41233
|
|
|
3655499 |
---
|
|
|
3655499 |
diff --git a/tumblerd/main.c b/tumblerd/main.c
|
|
|
3655499 |
index f2de4f0..f79049b 100644
|
|
|
3655499 |
--- a/tumblerd/main.c
|
|
|
3655499 |
+++ b/tumblerd/main.c
|
|
|
3655499 |
@@ -65,6 +65,7 @@ main (int argc,
|
|
|
3655499 |
TumblerService *service;
|
|
|
3655499 |
TumblerCacheService *cache_service;
|
|
|
3655499 |
GMainLoop *main_loop;
|
|
|
3655499 |
+ gboolean already_running = FALSE;
|
|
|
3655499 |
GError *error = NULL;
|
|
|
3655499 |
GList *providers;
|
|
|
3655499 |
GList *thumbnailers;
|
|
|
3655499 |
@@ -99,22 +100,6 @@ main (int argc,
|
|
|
3655499 |
/* create the lifecycle manager */
|
|
|
3655499 |
lifecycle_manager = tumbler_lifecycle_manager_new ();
|
|
|
3655499 |
|
|
|
3655499 |
- /* create the thumbnail cache service */
|
|
|
3655499 |
- cache_service = tumbler_cache_service_new (connection, lifecycle_manager);
|
|
|
3655499 |
-
|
|
|
3655499 |
- /* try to start the service and exit if that fails */
|
|
|
3655499 |
- if (!tumbler_cache_service_start (cache_service, &error))
|
|
|
3655499 |
- {
|
|
|
3655499 |
- g_warning (_("Failed to start the thumbnail cache service: %s"), error->message);
|
|
|
3655499 |
- g_error_free (error);
|
|
|
3655499 |
-
|
|
|
3655499 |
- g_object_unref (cache_service);
|
|
|
3655499 |
-
|
|
|
3655499 |
- dbus_g_connection_unref (connection);
|
|
|
3655499 |
-
|
|
|
3655499 |
- return EXIT_FAILURE;
|
|
|
3655499 |
- }
|
|
|
3655499 |
-
|
|
|
3655499 |
/* create the thumbnailer registry */
|
|
|
3655499 |
registry = tumbler_registry_new ();
|
|
|
3655499 |
|
|
|
3655499 |
@@ -152,6 +137,15 @@ main (int argc,
|
|
|
3655499 |
/* update the URI schemes / MIME types supported information */
|
|
|
3655499 |
tumbler_registry_update_supported (registry);
|
|
|
3655499 |
|
|
|
3655499 |
+ /* create the thumbnail cache service */
|
|
|
3655499 |
+ cache_service = tumbler_cache_service_new (connection, lifecycle_manager);
|
|
|
3655499 |
+
|
|
|
3655499 |
+ /* create the thumbnailer manager service */
|
|
|
3655499 |
+ manager = tumbler_manager_new (connection, lifecycle_manager, registry);
|
|
|
3655499 |
+
|
|
|
3655499 |
+ /* create the generic thumbnailer service */
|
|
|
3655499 |
+ service = tumbler_service_new (connection, lifecycle_manager, registry);
|
|
|
3655499 |
+
|
|
|
3655499 |
/* try to load specialized thumbnailers and exit if that fails */
|
|
|
3655499 |
if (!tumbler_registry_load (registry, &error))
|
|
|
3655499 |
{
|
|
|
3655499 |
@@ -159,49 +153,80 @@ main (int argc,
|
|
|
3655499 |
error->message);
|
|
|
3655499 |
g_error_free (error);
|
|
|
3655499 |
|
|
|
3655499 |
- g_object_unref (registry);
|
|
|
3655499 |
+ g_object_unref (service);
|
|
|
3655499 |
+ g_object_unref (manager);
|
|
|
3655499 |
g_object_unref (cache_service);
|
|
|
3655499 |
+ g_object_unref (registry);
|
|
|
3655499 |
|
|
|
3655499 |
dbus_g_connection_unref (connection);
|
|
|
3655499 |
|
|
|
3655499 |
return EXIT_FAILURE;
|
|
|
3655499 |
}
|
|
|
3655499 |
|
|
|
3655499 |
- /* create the thumbnailer manager service */
|
|
|
3655499 |
- manager = tumbler_manager_new (connection, lifecycle_manager, registry);
|
|
|
3655499 |
+ /* try to start the service and exit if that fails */
|
|
|
3655499 |
+ if (!tumbler_cache_service_start (cache_service, &error))
|
|
|
3655499 |
+ {
|
|
|
3655499 |
+ if (error->domain == DBUS_GERROR && error->code == DBUS_GERROR_ADDRESS_IN_USE)
|
|
|
3655499 |
+ already_running = TRUE;
|
|
|
3655499 |
+
|
|
|
3655499 |
+ g_warning (_("Failed to start the thumbnail cache service: %s"), error->message);
|
|
|
3655499 |
+ g_error_free (error);
|
|
|
3655499 |
+
|
|
|
3655499 |
+ g_object_unref (service);
|
|
|
3655499 |
+ g_object_unref (manager);
|
|
|
3655499 |
+ g_object_unref (cache_service);
|
|
|
3655499 |
+ g_object_unref (registry);
|
|
|
3655499 |
+
|
|
|
3655499 |
+ dbus_g_connection_unref (connection);
|
|
|
3655499 |
+
|
|
|
3655499 |
+ if (already_running)
|
|
|
3655499 |
+ return EXIT_SUCCESS;
|
|
|
3655499 |
+ else
|
|
|
3655499 |
+ return EXIT_FAILURE;
|
|
|
3655499 |
+ }
|
|
|
3655499 |
|
|
|
3655499 |
/* try to start the service and exit if that fails */
|
|
|
3655499 |
if (!tumbler_manager_start (manager, &error))
|
|
|
3655499 |
{
|
|
|
3655499 |
+ if (error->domain == DBUS_GERROR && error->code == DBUS_GERROR_ADDRESS_IN_USE)
|
|
|
3655499 |
+ already_running = TRUE;
|
|
|
3655499 |
+
|
|
|
3655499 |
g_warning (_("Failed to start the thumbnailer manager: %s"), error->message);
|
|
|
3655499 |
g_error_free (error);
|
|
|
3655499 |
|
|
|
3655499 |
+ g_object_unref (service);
|
|
|
3655499 |
g_object_unref (manager);
|
|
|
3655499 |
- g_object_unref (registry);
|
|
|
3655499 |
g_object_unref (cache_service);
|
|
|
3655499 |
+ g_object_unref (registry);
|
|
|
3655499 |
|
|
|
3655499 |
dbus_g_connection_unref (connection);
|
|
|
3655499 |
|
|
|
3655499 |
- return EXIT_FAILURE;
|
|
|
3655499 |
+ if (already_running)
|
|
|
3655499 |
+ return EXIT_SUCCESS;
|
|
|
3655499 |
+ else
|
|
|
3655499 |
+ return EXIT_FAILURE;
|
|
|
3655499 |
}
|
|
|
3655499 |
|
|
|
3655499 |
- /* create the generic thumbnailer service */
|
|
|
3655499 |
- service = tumbler_service_new (connection, lifecycle_manager, registry);
|
|
|
3655499 |
-
|
|
|
3655499 |
/* try to start the service and exit if that fails */
|
|
|
3655499 |
if (!tumbler_service_start (service, &error))
|
|
|
3655499 |
{
|
|
|
3655499 |
+ if (error->domain == DBUS_GERROR && error->code == DBUS_GERROR_ADDRESS_IN_USE)
|
|
|
3655499 |
+ already_running = TRUE;
|
|
|
3655499 |
+
|
|
|
3655499 |
g_warning (_("Failed to start the thumbnailer service: %s"), error->message);
|
|
|
3655499 |
g_error_free (error);
|
|
|
3655499 |
|
|
|
3655499 |
g_object_unref (service);
|
|
|
3655499 |
g_object_unref (manager);
|
|
|
3655499 |
- g_object_unref (registry);
|
|
|
3655499 |
g_object_unref (cache_service);
|
|
|
3655499 |
+ g_object_unref (registry);
|
|
|
3655499 |
|
|
|
3655499 |
dbus_g_connection_unref (connection);
|
|
|
3655499 |
|
|
|
3655499 |
- return EXIT_FAILURE;
|
|
|
3655499 |
+ if (already_running)
|
|
|
3655499 |
+ return EXIT_SUCCESS;
|
|
|
3655499 |
+ else
|
|
|
3655499 |
+ return EXIT_FAILURE;
|
|
|
3655499 |
}
|
|
|
3655499 |
|
|
|
3655499 |
/* create a new main loop */
|
|
|
3655499 |
@@ -220,8 +245,8 @@ main (int argc,
|
|
|
3655499 |
/* shut our services down and release all objects */
|
|
|
3655499 |
g_object_unref (service);
|
|
|
3655499 |
g_object_unref (manager);
|
|
|
3655499 |
- g_object_unref (registry);
|
|
|
3655499 |
g_object_unref (cache_service);
|
|
|
3655499 |
+ g_object_unref (registry);
|
|
|
3655499 |
g_object_unref (lifecycle_manager);
|
|
|
3655499 |
|
|
|
3655499 |
/* disconnect from the D-Bus session bus */
|
|
|
3655499 |
diff --git a/tumblerd/tumbler-cache-service.c b/tumblerd/tumbler-cache-service.c
|
|
|
3655499 |
index f13177c..f6b2dc5 100644
|
|
|
3655499 |
--- a/tumblerd/tumbler-cache-service.c
|
|
|
3655499 |
+++ b/tumblerd/tumbler-cache-service.c
|
|
|
3655499 |
@@ -174,6 +174,15 @@ tumbler_cache_service_constructed (GObject *object)
|
|
|
3655499 |
service, 1, FALSE, NULL);
|
|
|
3655499 |
service->cleanup_pool = g_thread_pool_new (tumbler_cache_service_cleanup_thread,
|
|
|
3655499 |
service, 1, FALSE, NULL);
|
|
|
3655499 |
+
|
|
|
3655499 |
+ /* everything's fine, install the cache type D-Bus info */
|
|
|
3655499 |
+ dbus_g_object_type_install_info (G_OBJECT_TYPE (service),
|
|
|
3655499 |
+ &dbus_glib_tumbler_cache_service_object_info);
|
|
|
3655499 |
+
|
|
|
3655499 |
+ /* register the cache instance as a handler of the cache interface */
|
|
|
3655499 |
+ dbus_g_connection_register_g_object (service->connection,
|
|
|
3655499 |
+ "/org/freedesktop/thumbnails/Cache1",
|
|
|
3655499 |
+ G_OBJECT (service));
|
|
|
3655499 |
}
|
|
|
3655499 |
|
|
|
3655499 |
|
|
|
3655499 |
@@ -400,7 +409,19 @@ tumbler_cache_service_start (TumblerCacheService *service,
|
|
|
3655499 |
DBUS_NAME_FLAG_DO_NOT_QUEUE, &dbus_error);
|
|
|
3655499 |
|
|
|
3655499 |
/* check if that failed */
|
|
|
3655499 |
- if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
|
|
|
3655499 |
+ if (result == DBUS_REQUEST_NAME_REPLY_EXISTS)
|
|
|
3655499 |
+ {
|
|
|
3655499 |
+ if (error != NULL)
|
|
|
3655499 |
+ {
|
|
|
3655499 |
+ g_set_error (error, DBUS_GERROR, DBUS_GERROR_ADDRESS_IN_USE,
|
|
|
3655499 |
+ _("Another thumbnail cache service is already running"));
|
|
|
3655499 |
+ }
|
|
|
3655499 |
+
|
|
|
3655499 |
+ g_mutex_unlock (service->mutex);
|
|
|
3655499 |
+
|
|
|
3655499 |
+ return FALSE;
|
|
|
3655499 |
+ }
|
|
|
3655499 |
+ else if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
|
|
|
3655499 |
{
|
|
|
3655499 |
/* propagate the D-Bus error */
|
|
|
3655499 |
if (dbus_error_is_set (&dbus_error))
|
|
|
3655499 |
@@ -421,15 +442,6 @@ tumbler_cache_service_start (TumblerCacheService *service,
|
|
|
3655499 |
return FALSE;
|
|
|
3655499 |
}
|
|
|
3655499 |
|
|
|
3655499 |
- /* everything's fine, install the cache type D-Bus info */
|
|
|
3655499 |
- dbus_g_object_type_install_info (G_OBJECT_TYPE (service),
|
|
|
3655499 |
- &dbus_glib_tumbler_cache_service_object_info);
|
|
|
3655499 |
-
|
|
|
3655499 |
- /* register the cache instance as a handler of the cache interface */
|
|
|
3655499 |
- dbus_g_connection_register_g_object (service->connection,
|
|
|
3655499 |
- "/org/freedesktop/thumbnails/Cache1",
|
|
|
3655499 |
- G_OBJECT (service));
|
|
|
3655499 |
-
|
|
|
3655499 |
g_mutex_unlock (service->mutex);
|
|
|
3655499 |
|
|
|
3655499 |
return TRUE;
|
|
|
3655499 |
diff --git a/tumblerd/tumbler-manager.c b/tumblerd/tumbler-manager.c
|
|
|
3655499 |
index 73e6778..feb2943 100644
|
|
|
3655499 |
--- a/tumblerd/tumbler-manager.c
|
|
|
3655499 |
+++ b/tumblerd/tumbler-manager.c
|
|
|
3655499 |
@@ -63,6 +63,7 @@ typedef struct _ThumbnailerInfo ThumbnailerInfo;
|
|
|
3655499 |
|
|
|
3655499 |
|
|
|
3655499 |
|
|
|
3655499 |
+static void tumbler_manager_constructed (GObject *object);
|
|
|
3655499 |
static void tumbler_manager_finalize (GObject *object);
|
|
|
3655499 |
static void tumbler_manager_get_property (GObject *object,
|
|
|
3655499 |
guint prop_id,
|
|
|
3655499 |
@@ -158,6 +159,7 @@ tumbler_manager_class_init (TumblerManagerClass *klass)
|
|
|
3655499 |
GObjectClass *gobject_class;
|
|
|
3655499 |
|
|
|
3655499 |
gobject_class = G_OBJECT_CLASS (klass);
|
|
|
3655499 |
+ gobject_class->constructed = tumbler_manager_constructed;
|
|
|
3655499 |
gobject_class->finalize = tumbler_manager_finalize;
|
|
|
3655499 |
gobject_class->get_property = tumbler_manager_get_property;
|
|
|
3655499 |
gobject_class->set_property = tumbler_manager_set_property;
|
|
|
3655499 |
@@ -198,6 +200,25 @@ tumbler_manager_init (TumblerManager *manager)
|
|
|
3655499 |
|
|
|
3655499 |
|
|
|
3655499 |
|
|
|
3655499 |
+
|
|
|
3655499 |
+
|
|
|
3655499 |
+static void
|
|
|
3655499 |
+tumbler_manager_constructed (GObject *object)
|
|
|
3655499 |
+{
|
|
|
3655499 |
+ TumblerManager *manager = TUMBLER_MANAGER (object);
|
|
|
3655499 |
+
|
|
|
3655499 |
+ /* everything's fine, install the manager type D-Bus info */
|
|
|
3655499 |
+ dbus_g_object_type_install_info (G_OBJECT_TYPE (manager),
|
|
|
3655499 |
+ &dbus_glib_tumbler_manager_object_info);
|
|
|
3655499 |
+
|
|
|
3655499 |
+ /* register the manager instance as a handler of the manager interface */
|
|
|
3655499 |
+ dbus_g_connection_register_g_object (manager->connection,
|
|
|
3655499 |
+ "/org/freedesktop/thumbnails/Manager1",
|
|
|
3655499 |
+ G_OBJECT (manager));
|
|
|
3655499 |
+}
|
|
|
3655499 |
+
|
|
|
3655499 |
+
|
|
|
3655499 |
+
|
|
|
3655499 |
static void
|
|
|
3655499 |
tumbler_manager_finalize (GObject *object)
|
|
|
3655499 |
{
|
|
|
3655499 |
@@ -1838,7 +1859,19 @@ tumbler_manager_start (TumblerManager *manager,
|
|
|
3655499 |
DBUS_NAME_FLAG_DO_NOT_QUEUE, &dbus_error);
|
|
|
3655499 |
|
|
|
3655499 |
/* check if that failed */
|
|
|
3655499 |
- if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
|
|
|
3655499 |
+ if (result == DBUS_REQUEST_NAME_REPLY_EXISTS)
|
|
|
3655499 |
+ {
|
|
|
3655499 |
+ if (error != NULL)
|
|
|
3655499 |
+ {
|
|
|
3655499 |
+ g_set_error (error, DBUS_GERROR, DBUS_GERROR_ADDRESS_IN_USE,
|
|
|
3655499 |
+ _("Another thumbnail cache service is already running"));
|
|
|
3655499 |
+ }
|
|
|
3655499 |
+
|
|
|
3655499 |
+ g_mutex_unlock (manager->mutex);
|
|
|
3655499 |
+
|
|
|
3655499 |
+ return FALSE;
|
|
|
3655499 |
+ }
|
|
|
3655499 |
+ else if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
|
|
|
3655499 |
{
|
|
|
3655499 |
/* propagate the D-Bus error */
|
|
|
3655499 |
if (dbus_error_is_set (&dbus_error))
|
|
|
3655499 |
@@ -1860,15 +1893,6 @@ tumbler_manager_start (TumblerManager *manager,
|
|
|
3655499 |
return FALSE;
|
|
|
3655499 |
}
|
|
|
3655499 |
|
|
|
3655499 |
- /* everything's fine, install the manager type D-Bus info */
|
|
|
3655499 |
- dbus_g_object_type_install_info (G_OBJECT_TYPE (manager),
|
|
|
3655499 |
- &dbus_glib_tumbler_manager_object_info);
|
|
|
3655499 |
-
|
|
|
3655499 |
- /* register the manager instance as a handler of the manager interface */
|
|
|
3655499 |
- dbus_g_connection_register_g_object (manager->connection,
|
|
|
3655499 |
- "/org/freedesktop/thumbnails/Manager1",
|
|
|
3655499 |
- G_OBJECT (manager));
|
|
|
3655499 |
-
|
|
|
3655499 |
g_mutex_unlock (manager->mutex);
|
|
|
3655499 |
|
|
|
3655499 |
/* load thumbnailers installed into the system permanently */
|
|
|
3655499 |
diff --git a/tumblerd/tumbler-service.c b/tumblerd/tumbler-service.c
|
|
|
3655499 |
index 92ab7ac..8214a45 100644
|
|
|
3655499 |
--- a/tumblerd/tumbler-service.c
|
|
|
3655499 |
+++ b/tumblerd/tumbler-service.c
|
|
|
3655499 |
@@ -295,6 +295,15 @@ tumbler_service_constructed (GObject *object)
|
|
|
3655499 |
scheduler = tumbler_group_scheduler_new ("background");
|
|
|
3655499 |
tumbler_service_add_scheduler (service, scheduler);
|
|
|
3655499 |
g_object_unref (scheduler);
|
|
|
3655499 |
+
|
|
|
3655499 |
+ /* everything is fine, install the generic thumbnailer D-Bus info */
|
|
|
3655499 |
+ dbus_g_object_type_install_info (G_OBJECT_TYPE (service),
|
|
|
3655499 |
+ &dbus_glib_tumbler_service_object_info);
|
|
|
3655499 |
+
|
|
|
3655499 |
+ /* register the service instance as a handler of this interface */
|
|
|
3655499 |
+ dbus_g_connection_register_g_object (service->connection,
|
|
|
3655499 |
+ THUMBNAILER_PATH,
|
|
|
3655499 |
+ G_OBJECT (service));
|
|
|
3655499 |
}
|
|
|
3655499 |
|
|
|
3655499 |
|
|
|
3655499 |
@@ -744,7 +753,19 @@ tumbler_service_start (TumblerService *service,
|
|
|
3655499 |
DBUS_NAME_FLAG_DO_NOT_QUEUE, &dbus_error);
|
|
|
3655499 |
|
|
|
3655499 |
/* check if that failed */
|
|
|
3655499 |
- if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
|
|
|
3655499 |
+ if (result == DBUS_REQUEST_NAME_REPLY_EXISTS)
|
|
|
3655499 |
+ {
|
|
|
3655499 |
+ if (error != NULL)
|
|
|
3655499 |
+ {
|
|
|
3655499 |
+ g_set_error (error, DBUS_GERROR, DBUS_GERROR_ADDRESS_IN_USE,
|
|
|
3655499 |
+ _("Another thumbnail cache service is already running"));
|
|
|
3655499 |
+ }
|
|
|
3655499 |
+
|
|
|
3655499 |
+ g_mutex_unlock (service->mutex);
|
|
|
3655499 |
+
|
|
|
3655499 |
+ return FALSE;
|
|
|
3655499 |
+ }
|
|
|
3655499 |
+ else if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
|
|
|
3655499 |
{
|
|
|
3655499 |
/* propagate the D-Bus error */
|
|
|
3655499 |
if (dbus_error_is_set (&dbus_error))
|
|
|
3655499 |
@@ -765,15 +786,6 @@ tumbler_service_start (TumblerService *service,
|
|
|
3655499 |
return FALSE;
|
|
|
3655499 |
}
|
|
|
3655499 |
|
|
|
3655499 |
- /* everything is fine, install the generic thumbnailer D-Bus info */
|
|
|
3655499 |
- dbus_g_object_type_install_info (G_OBJECT_TYPE (service),
|
|
|
3655499 |
- &dbus_glib_tumbler_service_object_info);
|
|
|
3655499 |
-
|
|
|
3655499 |
- /* register the service instance as a handler of this interface */
|
|
|
3655499 |
- dbus_g_connection_register_g_object (service->connection,
|
|
|
3655499 |
- THUMBNAILER_PATH,
|
|
|
3655499 |
- G_OBJECT (service));
|
|
|
3655499 |
-
|
|
|
3655499 |
g_mutex_unlock (service->mutex);
|
|
|
3655499 |
|
|
|
3655499 |
return TRUE;
|
|
|
3655499 |
--
|
|
|
3655499 |
cgit
|