|
|
4b6d7b |
diff -up evolution-3.12.11/e-util/e-client-cache.c.client-cache-stuck evolution-3.12.11/e-util/e-client-cache.c
|
|
|
4b6d7b |
--- evolution-3.12.11/e-util/e-client-cache.c.client-cache-stuck 2015-01-27 14:46:14.000000000 +0100
|
|
|
4b6d7b |
+++ evolution-3.12.11/e-util/e-client-cache.c 2015-07-15 18:08:54.368866342 +0200
|
|
|
4b6d7b |
@@ -531,8 +531,12 @@ client_cache_process_results (ClientData
|
|
|
4b6d7b |
if (client != NULL) {
|
|
|
4b6d7b |
EClientCache *client_cache;
|
|
|
4b6d7b |
|
|
|
4b6d7b |
- /* Make sure we're not leaking a reference. */
|
|
|
4b6d7b |
- g_warn_if_fail (client_data->client == NULL);
|
|
|
4b6d7b |
+ /* Make sure we're not leaking a reference. This can happen when
|
|
|
4b6d7b |
+ a synchronous and an asynchronous open are interleaving. The
|
|
|
4b6d7b |
+ synchronous open bypasses pending openings, thus can eventually
|
|
|
4b6d7b |
+ overwrite, or preset, the client.
|
|
|
4b6d7b |
+ */
|
|
|
4b6d7b |
+ g_clear_object (&client_data->client);
|
|
|
4b6d7b |
|
|
|
4b6d7b |
client_data->client = g_object_ref (client);
|
|
|
4b6d7b |
client_data->dead_backend = FALSE;
|
|
|
4b6d7b |
@@ -1047,28 +1051,6 @@ e_client_cache_ref_registry (EClientCach
|
|
|
4b6d7b |
return g_object_ref (client_cache->priv->registry);
|
|
|
4b6d7b |
}
|
|
|
4b6d7b |
|
|
|
4b6d7b |
-typedef struct _GetClientSyncData {
|
|
|
4b6d7b |
- GMutex mutex;
|
|
|
4b6d7b |
- EAsyncClosure *closure;
|
|
|
4b6d7b |
-} GetClientSyncData;
|
|
|
4b6d7b |
-
|
|
|
4b6d7b |
-static void
|
|
|
4b6d7b |
-client_cache_get_client_sync_cb (GObject *source_object,
|
|
|
4b6d7b |
- GAsyncResult *result,
|
|
|
4b6d7b |
- gpointer user_data)
|
|
|
4b6d7b |
-{
|
|
|
4b6d7b |
- GetClientSyncData *data = user_data;
|
|
|
4b6d7b |
-
|
|
|
4b6d7b |
- g_return_if_fail (E_IS_CLIENT_CACHE (source_object));
|
|
|
4b6d7b |
- g_return_if_fail (data != NULL);
|
|
|
4b6d7b |
-
|
|
|
4b6d7b |
- g_mutex_lock (&data->mutex);
|
|
|
4b6d7b |
-
|
|
|
4b6d7b |
- e_async_closure_callback (source_object, result, data->closure);
|
|
|
4b6d7b |
-
|
|
|
4b6d7b |
- g_mutex_unlock (&data->mutex);
|
|
|
4b6d7b |
-}
|
|
|
4b6d7b |
-
|
|
|
4b6d7b |
/**
|
|
|
4b6d7b |
* e_client_cache_get_client_sync:
|
|
|
4b6d7b |
* @client_cache: an #EClientCache
|
|
|
4b6d7b |
@@ -1116,37 +1098,68 @@ e_client_cache_get_client_sync (EClientC
|
|
|
4b6d7b |
GCancellable *cancellable,
|
|
|
4b6d7b |
GError **error)
|
|
|
4b6d7b |
{
|
|
|
4b6d7b |
- GetClientSyncData data;
|
|
|
4b6d7b |
- GAsyncResult *result;
|
|
|
4b6d7b |
- EClient *client;
|
|
|
4b6d7b |
+ ClientData *client_data;
|
|
|
4b6d7b |
+ EClient *client = NULL;
|
|
|
4b6d7b |
+ GError *local_error = NULL;
|
|
|
4b6d7b |
|
|
|
4b6d7b |
g_return_val_if_fail (E_IS_CLIENT_CACHE (client_cache), NULL);
|
|
|
4b6d7b |
g_return_val_if_fail (E_IS_SOURCE (source), NULL);
|
|
|
4b6d7b |
g_return_val_if_fail (extension_name != NULL, NULL);
|
|
|
4b6d7b |
|
|
|
4b6d7b |
- g_mutex_init (&data.mutex);
|
|
|
4b6d7b |
- g_mutex_lock (&data.mutex);
|
|
|
4b6d7b |
+ client_data = client_ht_lookup (client_cache, source, extension_name);
|
|
|
4b6d7b |
|
|
|
4b6d7b |
- e_client_cache_get_client (
|
|
|
4b6d7b |
- client_cache, source, extension_name,cancellable,
|
|
|
4b6d7b |
- client_cache_get_client_sync_cb, &data);
|
|
|
4b6d7b |
+ if (client_data == NULL) {
|
|
|
4b6d7b |
+ g_set_error (
|
|
|
4b6d7b |
+ error, G_IO_ERROR,
|
|
|
4b6d7b |
+ G_IO_ERROR_INVALID_ARGUMENT,
|
|
|
4b6d7b |
+ _("Cannot create a client object from "
|
|
|
4b6d7b |
+ "extension name '%s'"), extension_name);
|
|
|
4b6d7b |
+ return NULL;
|
|
|
4b6d7b |
+ }
|
|
|
4b6d7b |
|
|
|
4b6d7b |
- /* This is needed, because e_async_closure_new() pushes its own thread default main context,
|
|
|
4b6d7b |
- which was later taken into an EClient within e_client_cache_get_client(), but that's wrong,
|
|
|
4b6d7b |
- because that main context effectively dies at the end of this function. */
|
|
|
4b6d7b |
- data.closure = e_async_closure_new ();
|
|
|
4b6d7b |
+ g_mutex_lock (&client_data->lock);
|
|
|
4b6d7b |
|
|
|
4b6d7b |
- g_mutex_unlock (&data.mutex);
|
|
|
4b6d7b |
+ if (client_data->client != NULL)
|
|
|
4b6d7b |
+ client = g_object_ref (client_data->client);
|
|
|
4b6d7b |
|
|
|
4b6d7b |
- result = e_async_closure_wait (data.closure);
|
|
|
4b6d7b |
+ g_mutex_unlock (&client_data->lock);
|
|
|
4b6d7b |
|
|
|
4b6d7b |
- client = e_client_cache_get_client_finish (
|
|
|
4b6d7b |
- client_cache, result, error);
|
|
|
4b6d7b |
+ /* If a cached EClient already exists, we're done. */
|
|
|
4b6d7b |
+ if (client != NULL) {
|
|
|
4b6d7b |
+ client_data_unref (client_data);
|
|
|
4b6d7b |
+ return client;
|
|
|
4b6d7b |
+ }
|
|
|
4b6d7b |
|
|
|
4b6d7b |
- g_mutex_lock (&data.mutex);
|
|
|
4b6d7b |
- e_async_closure_free (data.closure);
|
|
|
4b6d7b |
- g_mutex_unlock (&data.mutex);
|
|
|
4b6d7b |
- g_mutex_clear (&data.mutex);
|
|
|
4b6d7b |
+ /* Create an appropriate EClient instance for the extension
|
|
|
4b6d7b |
+ * name. The client_ht_lookup() call above ensures us that
|
|
|
4b6d7b |
+ * one of these options will match. */
|
|
|
4b6d7b |
+
|
|
|
4b6d7b |
+ if (g_str_equal (extension_name, E_SOURCE_EXTENSION_ADDRESS_BOOK)) {
|
|
|
4b6d7b |
+ client = e_book_client_connect_sync (source,
|
|
|
4b6d7b |
+ cancellable, &local_error);
|
|
|
4b6d7b |
+ } else if (g_str_equal (extension_name, E_SOURCE_EXTENSION_CALENDAR)) {
|
|
|
4b6d7b |
+ client = e_cal_client_connect_sync (
|
|
|
4b6d7b |
+ source, E_CAL_CLIENT_SOURCE_TYPE_EVENTS,
|
|
|
4b6d7b |
+ cancellable, &local_error);
|
|
|
4b6d7b |
+ } else if (g_str_equal (extension_name, E_SOURCE_EXTENSION_MEMO_LIST)) {
|
|
|
4b6d7b |
+ client = e_cal_client_connect_sync (
|
|
|
4b6d7b |
+ source, E_CAL_CLIENT_SOURCE_TYPE_MEMOS,
|
|
|
4b6d7b |
+ cancellable, &local_error);
|
|
|
4b6d7b |
+ } else if (g_str_equal (extension_name, E_SOURCE_EXTENSION_TASK_LIST)) {
|
|
|
4b6d7b |
+ client = e_cal_client_connect_sync (
|
|
|
4b6d7b |
+ source, E_CAL_CLIENT_SOURCE_TYPE_TASKS,
|
|
|
4b6d7b |
+ cancellable, &local_error);
|
|
|
4b6d7b |
+ } else {
|
|
|
4b6d7b |
+ g_warn_if_reached (); /* Should never happen. */
|
|
|
4b6d7b |
+ }
|
|
|
4b6d7b |
+
|
|
|
4b6d7b |
+ if (client)
|
|
|
4b6d7b |
+ client_cache_process_results (client_data, client, local_error);
|
|
|
4b6d7b |
+
|
|
|
4b6d7b |
+ if (local_error)
|
|
|
4b6d7b |
+ g_propagate_error (error, local_error);
|
|
|
4b6d7b |
+
|
|
|
4b6d7b |
+ client_data_unref (client_data);
|
|
|
4b6d7b |
|
|
|
4b6d7b |
return client;
|
|
|
4b6d7b |
}
|