Blame SOURCES/evolution-data-server-3.12.11-async-closures-thread-safety.patch

5e6360
diff -up evolution-data-server-3.12.11/camel/camel-async-closure.c.async-closures-thread-safety evolution-data-server-3.12.11/camel/camel-async-closure.c
5e6360
--- evolution-data-server-3.12.11/camel/camel-async-closure.c.async-closures-thread-safety	2014-03-24 10:07:52.000000000 +0100
5e6360
+++ evolution-data-server-3.12.11/camel/camel-async-closure.c	2015-06-01 21:55:07.711600144 +0200
5e6360
@@ -54,6 +54,8 @@ struct _CamelAsyncClosure {
5e6360
 	GMainLoop *loop;
5e6360
 	GMainContext *context;
5e6360
 	GAsyncResult *result;
5e6360
+	gboolean finished;
5e6360
+	GMutex lock;
5e6360
 };
5e6360
 
5e6360
 /**
5e6360
@@ -73,12 +75,26 @@ camel_async_closure_new (void)
5e6360
 	closure = g_slice_new0 (CamelAsyncClosure);
5e6360
 	closure->context = g_main_context_new ();
5e6360
 	closure->loop = g_main_loop_new (closure->context, FALSE);
5e6360
+	closure->finished = FALSE;
5e6360
+	g_mutex_init (&closure->lock);
5e6360
 
5e6360
 	g_main_context_push_thread_default (closure->context);
5e6360
 
5e6360
 	return closure;
5e6360
 }
5e6360
 
5e6360
+static gboolean
5e6360
+camel_async_closure_unlock_mutex_cb (gpointer user_data)
5e6360
+{
5e6360
+	CamelAsyncClosure *closure = user_data;
5e6360
+
5e6360
+	g_return_val_if_fail (closure != NULL, FALSE);
5e6360
+
5e6360
+	g_mutex_unlock (&closure->lock);
5e6360
+
5e6360
+	return FALSE;
5e6360
+}
5e6360
+
5e6360
 /**
5e6360
  * camel_async_closure_wait:
5e6360
  * @closure: a #CamelAsyncClosure
5e6360
@@ -99,7 +115,22 @@ camel_async_closure_wait (CamelAsyncClos
5e6360
 {
5e6360
 	g_return_val_if_fail (closure != NULL, NULL);
5e6360
 
5e6360
-	g_main_loop_run (closure->loop);
5e6360
+	g_mutex_lock (&closure->lock);
5e6360
+	if (closure->finished) {
5e6360
+		g_mutex_unlock (&closure->lock);
5e6360
+	} else {
5e6360
+		GSource *idle_source;
5e6360
+
5e6360
+		/* Unlock the closure->lock in the main loop, to ensure thread safety.
5e6360
+		   It should be processed before anything else, otherwise deadlock happens. */
5e6360
+		idle_source = g_idle_source_new ();
5e6360
+		g_source_set_callback (idle_source, camel_async_closure_unlock_mutex_cb, closure, NULL);
5e6360
+		g_source_set_priority (idle_source, G_PRIORITY_HIGH * 2);
5e6360
+		g_source_attach (idle_source, closure->context);
5e6360
+		g_source_unref (idle_source);
5e6360
+
5e6360
+		g_main_loop_run (closure->loop);
5e6360
+	}
5e6360
 
5e6360
 	return closure->result;
5e6360
 }
5e6360
@@ -122,8 +153,10 @@ camel_async_closure_free (CamelAsyncClos
5e6360
 	g_main_loop_unref (closure->loop);
5e6360
 	g_main_context_unref (closure->context);
5e6360
 
5e6360
-	if (closure->result != NULL)
5e6360
-		g_object_unref (closure->result);
5e6360
+	g_mutex_lock (&closure->lock);
5e6360
+	g_clear_object (&closure->result);
5e6360
+	g_mutex_unlock (&closure->lock);
5e6360
+	g_mutex_clear (&closure->lock);
5e6360
 
5e6360
 	g_slice_free (CamelAsyncClosure, closure);
5e6360
 }
5e6360
@@ -153,10 +186,15 @@ camel_async_closure_callback (GObject *s
5e6360
 
5e6360
 	real_closure = closure;
5e6360
 
5e6360
+	g_mutex_lock (&real_closure->lock);
5e6360
+
5e6360
 	/* Replace any previous result. */
5e6360
 	if (real_closure->result != NULL)
5e6360
 		g_object_unref (real_closure->result);
5e6360
 	real_closure->result = g_object_ref (result);
5e6360
+	real_closure->finished = TRUE;
5e6360
+
5e6360
+	g_mutex_unlock (&real_closure->lock);
5e6360
 
5e6360
 	g_main_loop_quit (real_closure->loop);
5e6360
 }
5e6360
diff -up evolution-data-server-3.12.11/libedataserver/e-data-server-util.c.async-closures-thread-safety evolution-data-server-3.12.11/libedataserver/e-data-server-util.c
5e6360
--- evolution-data-server-3.12.11/libedataserver/e-data-server-util.c.async-closures-thread-safety	2014-11-11 18:40:25.000000000 +0100
5e6360
+++ evolution-data-server-3.12.11/libedataserver/e-data-server-util.c	2015-06-01 21:55:07.712600137 +0200
5e6360
@@ -1523,6 +1523,8 @@ struct _EAsyncClosure {
5e6360
 	GMainLoop *loop;
5e6360
 	GMainContext *context;
5e6360
 	GAsyncResult *result;
5e6360
+	gboolean finished;
5e6360
+	GMutex lock;
5e6360
 };
5e6360
 
5e6360
 /**
5e6360
@@ -1542,12 +1544,26 @@ e_async_closure_new (void)
5e6360
 	closure = g_slice_new0 (EAsyncClosure);
5e6360
 	closure->context = g_main_context_new ();
5e6360
 	closure->loop = g_main_loop_new (closure->context, FALSE);
5e6360
+	closure->finished = FALSE;
5e6360
+	g_mutex_init (&closure->lock);
5e6360
 
5e6360
 	g_main_context_push_thread_default (closure->context);
5e6360
 
5e6360
 	return closure;
5e6360
 }
5e6360
 
5e6360
+static gboolean
5e6360
+e_async_closure_unlock_mutex_cb (gpointer user_data)
5e6360
+{
5e6360
+	EAsyncClosure *closure = user_data;
5e6360
+
5e6360
+	g_return_val_if_fail (closure != NULL, FALSE);
5e6360
+
5e6360
+	g_mutex_unlock (&closure->lock);
5e6360
+
5e6360
+	return FALSE;
5e6360
+}
5e6360
+
5e6360
 /**
5e6360
  * e_async_closure_wait:
5e6360
  * @closure: an #EAsyncClosure
5e6360
@@ -1568,7 +1584,22 @@ e_async_closure_wait (EAsyncClosure *clo
5e6360
 {
5e6360
 	g_return_val_if_fail (closure != NULL, NULL);
5e6360
 
5e6360
-	g_main_loop_run (closure->loop);
5e6360
+	g_mutex_lock (&closure->lock);
5e6360
+	if (closure->finished) {
5e6360
+		g_mutex_unlock (&closure->lock);
5e6360
+	} else {
5e6360
+		GSource *idle_source;
5e6360
+
5e6360
+		/* Unlock the closure->lock in the main loop, to ensure thread safety.
5e6360
+		   It should be processed before anything else, otherwise deadlock happens. */
5e6360
+		idle_source = g_idle_source_new ();
5e6360
+		g_source_set_callback (idle_source, e_async_closure_unlock_mutex_cb, closure, NULL);
5e6360
+		g_source_set_priority (idle_source, G_PRIORITY_HIGH * 2);
5e6360
+		g_source_attach (idle_source, closure->context);
5e6360
+		g_source_unref (idle_source);
5e6360
+
5e6360
+		g_main_loop_run (closure->loop);
5e6360
+	}
5e6360
 
5e6360
 	return closure->result;
5e6360
 }
5e6360
@@ -1591,8 +1622,10 @@ e_async_closure_free (EAsyncClosure *clo
5e6360
 	g_main_loop_unref (closure->loop);
5e6360
 	g_main_context_unref (closure->context);
5e6360
 
5e6360
-	if (closure->result != NULL)
5e6360
-		g_object_unref (closure->result);
5e6360
+	g_mutex_lock (&closure->lock);
5e6360
+	g_clear_object (&closure->result);
5e6360
+	g_mutex_unlock (&closure->lock);
5e6360
+	g_mutex_clear (&closure->lock);
5e6360
 
5e6360
 	g_slice_free (EAsyncClosure, closure);
5e6360
 }
5e6360
@@ -1622,10 +1655,15 @@ e_async_closure_callback (GObject *objec
5e6360
 
5e6360
 	real_closure = closure;
5e6360
 
5e6360
+	g_mutex_lock (&real_closure->lock);
5e6360
+
5e6360
 	/* Replace any previous result. */
5e6360
 	if (real_closure->result != NULL)
5e6360
 		g_object_unref (real_closure->result);
5e6360
 	real_closure->result = g_object_ref (result);
5e6360
+	real_closure->finished = TRUE;
5e6360
+
5e6360
+	g_mutex_unlock (&real_closure->lock);
5e6360
 
5e6360
 	g_main_loop_quit (real_closure->loop);
5e6360
 }