[evolution-data-server] Always hold EDBusServer when opening factory subprocess



commit e9dba19f746d84e2e2ef486cfc8e91f6050f56d4
Author: Milan Crha <mcrha redhat com>
Date:   Wed Sep 2 16:31:50 2015 +0200

    Always hold EDBusServer when opening factory subprocess
    
    It could happen that the opening of the subprocess took longer,
    and if it wasn't the first connection then the server's use-count
    wasn't increased, thus when the already opened connection had been
    closed meanwhile it could quit whole factory process with
    the pending subprocess open.
    
    This had been reported downstream at:
    https://bugzilla.redhat.com/show_bug.cgi?id=1259048

 libebackend/e-data-factory.c |   31 ++++++++++++++-----------------
 libebackend/e-dbus-server.c  |   14 ++++++++++++++
 2 files changed, 28 insertions(+), 17 deletions(-)
---
diff --git a/libebackend/e-data-factory.c b/libebackend/e-data-factory.c
index e072fb4..1f3880e 100644
--- a/libebackend/e-data-factory.c
+++ b/libebackend/e-data-factory.c
@@ -407,11 +407,10 @@ data_factory_connections_remove (EDataFactory *data_factory,
                        removed = TRUE;
                }
 
-               if (array->len == 0)
+               if (array->len == 0) {
                        g_hash_table_remove (connections, name);
-
-               if (g_hash_table_size (connections) == 0)
                        e_dbus_server_release (E_DBUS_SERVER (data_factory));
+               }
        }
 
        g_rec_mutex_unlock (&data_factory->priv->connections_lock);
@@ -507,6 +506,7 @@ data_factory_connections_add (EDataFactory *data_factory,
                        (GDestroyNotify) g_object_unref);
                g_hash_table_insert (
                        connections, g_strdup (name), array);
+               e_dbus_server_hold (E_DBUS_SERVER (data_factory));
        }
 
        g_ptr_array_add (array, g_object_ref (proxy));
@@ -551,15 +551,12 @@ data_factory_call_subprocess_backend_create_sync (EDataFactory *data_factory,
 
                g_free (object_path);
        } else {
-               g_rec_mutex_lock (&data_factory->priv->connections_lock);
-               if (g_hash_table_size (data_factory->priv->connections) == 0)
-                       e_dbus_server_release (E_DBUS_SERVER (data_factory));
-               g_rec_mutex_unlock (&data_factory->priv->connections_lock);
-
                g_return_if_fail (error != NULL);
                g_dbus_method_invocation_take_error (invocation, error);
        }
 
+       e_dbus_server_release (E_DBUS_SERVER (data_factory));
+
        g_mutex_lock (&data_factory->priv->spawn_subprocess_lock);
        if (data_factory->priv->spawn_subprocess_state == DATA_FACTORY_SPAWN_SUBPROCESS_BLOCKED)
                data_factory->priv->spawn_subprocess_state = DATA_FACTORY_SPAWN_SUBPROCESS_NONE;
@@ -759,17 +756,23 @@ data_factory_connections_remove_all (EDataFactory *data_factory)
 
        if (g_hash_table_size (connections) > 0) {
                GList *proxies, *l;
+               gint ii;
+
                proxies = data_factory_list_proxies (data_factory);
 
                for (l = proxies; l != NULL; l = g_list_next (l)) {
                        EDBusSubprocessBackend *proxy = l->data;
+
                        e_dbus_subprocess_backend_call_close_sync (proxy, NULL, NULL);
                }
 
                g_list_free_full (proxies, g_object_unref);
 
+               for (ii = 0; ii < g_hash_table_size (connections); ii++) {
+                       e_dbus_server_release (E_DBUS_SERVER (data_factory));
+               }
+
                g_hash_table_remove_all (connections);
-               e_dbus_server_release (E_DBUS_SERVER (data_factory));
        }
 
        g_rec_mutex_unlock (&data_factory->priv->connections_lock);
@@ -1291,10 +1294,7 @@ data_factory_spawn_subprocess_backend (EDataFactory *data_factory,
        }
 
        if (error != NULL) {
-               g_rec_mutex_lock (&priv->connections_lock);
-               if (g_hash_table_size (priv->connections) == 0)
-                       e_dbus_server_release (E_DBUS_SERVER (data_factory));
-               g_rec_mutex_unlock (&priv->connections_lock);
+               e_dbus_server_release (E_DBUS_SERVER (data_factory));
 
                if (sd) {
                        g_mutex_lock (&priv->subprocess_watched_ids_lock);
@@ -1371,10 +1371,7 @@ e_data_factory_spawn_subprocess_backend (EDataFactory *data_factory,
 
        /* Make sure the server will not quit due to inactivity while
           the subprocess is opening */
-       g_rec_mutex_lock (&data_factory->priv->connections_lock);
-       if (g_hash_table_size (data_factory->priv->connections) == 0)
-               e_dbus_server_hold (E_DBUS_SERVER (data_factory));
-       g_rec_mutex_unlock (&data_factory->priv->connections_lock);
+       e_dbus_server_hold (E_DBUS_SERVER (data_factory));
 
        data = data_factory_spawn_subprocess_backend_thread_data_new (
                data_factory, invocation, uid, extension_name, subprocess_path);
diff --git a/libebackend/e-dbus-server.c b/libebackend/e-dbus-server.c
index ea5bdc4..646e592 100644
--- a/libebackend/e-dbus-server.c
+++ b/libebackend/e-dbus-server.c
@@ -49,6 +49,8 @@ struct _EDBusServerPrivate {
        guint use_count;
        gboolean wait_for_client;
        EDBusServerExitCode exit_code;
+
+       GMutex property_lock;
 };
 
 enum {
@@ -148,6 +150,8 @@ dbus_server_finalize (GObject *object)
        if (priv->inactivity_timeout_id > 0)
                g_source_remove (priv->inactivity_timeout_id);
 
+       g_mutex_clear (&priv->property_lock);
+
        /* Chain up to parent's finalize() method. */
        G_OBJECT_CLASS (e_dbus_server_parent_class)->finalize (object);
 }
@@ -371,6 +375,8 @@ e_dbus_server_init (EDBusServer *server)
        server->priv->main_loop = g_main_loop_new (NULL, FALSE);
        server->priv->wait_for_client = FALSE;
 
+       g_mutex_init (&server->priv->property_lock);
+
 #ifdef G_OS_UNIX
        server->priv->hang_up_id = g_unix_signal_add (
                SIGHUP, dbus_server_hang_up_cb, server);
@@ -456,12 +462,16 @@ e_dbus_server_hold (EDBusServer *server)
 {
        g_return_if_fail (E_IS_DBUS_SERVER (server));
 
+       g_mutex_lock (&server->priv->property_lock);
+
        if (server->priv->inactivity_timeout_id > 0) {
                g_source_remove (server->priv->inactivity_timeout_id);
                server->priv->inactivity_timeout_id = 0;
        }
 
        server->priv->use_count++;
+
+       g_mutex_unlock (&server->priv->property_lock);
 }
 
 /**
@@ -483,6 +493,8 @@ e_dbus_server_release (EDBusServer *server)
        g_return_if_fail (E_IS_DBUS_SERVER (server));
        g_return_if_fail (server->priv->use_count > 0);
 
+       g_mutex_lock (&server->priv->property_lock);
+
        server->priv->use_count--;
 
        if (server->priv->use_count == 0) {
@@ -492,6 +504,8 @@ e_dbus_server_release (EDBusServer *server)
                                dbus_server_inactivity_timeout_cb,
                                server);
        }
+
+       g_mutex_unlock (&server->priv->property_lock);
 }
 
 /**


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]