[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