Patch: avoid hangs on cancelling send queue



	Hi,

	This patch avoids some hangs in TnyCamelSendQueue, that could happen
when we request to cancel in mainloop, but send queue thread is waiting
for a signal emission to be handled.

	The way we fix this is scheduling the cancel operation in the send
queue thread.

Changelog entry:
* libtinymail-camel/tny-camel-send-queue.c,
  libtinymail-camel/tny-camel-send-queue-priv.h: if queue is
  running when we cancel, then we request cancel to be done by
  the send queue thread.

-- 
José Dapena Paz <jdapena igalia com>
Igalia
diff --git a/ChangeLog b/ChangeLog
index 33b6c1e..6e141a9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2009-04-01  Jose Dapena Paz  <jdapena igalia com>
+
+	* libtinymail-camel/tny-camel-send-queue.c,
+	libtinymail-camel/tny-camel-send-queue-priv.h: if queue is
+	running when we cancel, then we request cancel to be done by
+	the send queue thread.
+
 2009-03-24  Jose Dapena Paz  <jdapena igalia com>
 
 	* libtinymailui-gtk/tny-gtk-folder-list-store.[ch]: added
diff --git a/libtinymail-camel/tny-camel-send-queue-priv.h b/libtinymail-camel/tny-camel-send-queue-priv.h
index 48998d7..3419d83 100644
--- a/libtinymail-camel/tny-camel-send-queue-priv.h
+++ b/libtinymail-camel/tny-camel-send-queue-priv.h
@@ -36,7 +36,9 @@ struct _TnyCamelSendQueuePriv
 	gboolean do_continue, is_running;
 	gboolean observer_attached;
 	gint pending_send_notifies;
-	GStaticMutex *running_lock; 
+	GStaticMutex *running_lock;
+	gboolean cancel_requested;
+	TnySendQueueCancelAction cancel_action;
 };
 
 #endif
diff --git a/libtinymail-camel/tny-camel-send-queue.c b/libtinymail-camel/tny-camel-send-queue.c
index e4f706d..dabd93a 100644
--- a/libtinymail-camel/tny-camel-send-queue.c
+++ b/libtinymail-camel/tny-camel-send-queue.c
@@ -602,6 +602,25 @@ wait_for_queue_start_notification (TnySendQueue *self)
 	g_slice_free (ControlInfo, info);
 }
 
+static void
+check_cancel (TnySendQueue *self, gboolean new_is_running, gboolean *cancel_requested)
+{
+	TnyCamelSendQueuePriv *priv = TNY_CAMEL_SEND_QUEUE_GET_PRIVATE (self);
+	TnySendQueueCancelAction cancel_action;
+
+	g_static_mutex_lock (priv->running_lock);
+	*cancel_requested = priv->cancel_requested;
+	cancel_action = priv->cancel_action;
+	priv->cancel_requested = FALSE;
+	priv->is_running = new_is_running;
+	g_static_mutex_unlock (priv->running_lock);
+	
+	if (cancel_requested) {
+		tny_send_queue_cancel (self, cancel_action, NULL);
+	}
+
+}
+
 
 static gpointer
 thread_main (gpointer data)
@@ -613,6 +632,7 @@ thread_main (gpointer data)
 	TnyList *list = NULL;
 	TnyDevice *device = info->device;
 	GHashTable *failed_headers = NULL;
+	gboolean cancel_requested = FALSE;
 
 	/* Wait here until the user receives the queue-start notification */
 	wait_for_queue_start_notification (self);
@@ -642,7 +662,7 @@ thread_main (gpointer data)
 
 	failed_headers = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
 
-	while ((length - g_hash_table_size (failed_headers)) > 0 && tny_device_is_online (device))
+	while ((length - g_hash_table_size (failed_headers)) > 0 && tny_device_is_online (device) && !cancel_requested)
 	{
 		TnyHeader *header = NULL;
 
@@ -763,6 +783,8 @@ thread_main (gpointer data)
 				g_object_unref (msg);
 			msg = NULL;
 
+			check_cancel (self, TRUE, &cancel_requested);
+
 			g_static_rec_mutex_lock (priv->todo_lock);
 			{
 				if (err == NULL) {
@@ -810,6 +832,8 @@ thread_main (gpointer data)
 
 		g_static_rec_mutex_unlock (priv->sending_lock);
 
+		check_cancel (self, TRUE, &cancel_requested);
+
 	}
 
 	tny_folder_sync_async (info->sentbox, TRUE, NULL, NULL, NULL);
@@ -846,9 +870,7 @@ errorhandler:
 
 	g_slice_free (MainThreadInfo, info);
 
-	g_static_mutex_lock (priv->running_lock);
-	priv->is_running = FALSE;
-	g_static_mutex_unlock (priv->running_lock);
+	check_cancel (self, FALSE, &cancel_requested);
 
 	/* Emit the queue-stop signal */
 	emit_queue_control_signals (self, TNY_SEND_QUEUE_STOP);
@@ -952,6 +974,16 @@ tny_camel_send_queue_cancel_default (TnySendQueue *self, TnySendQueueCancelActio
 	TnyList *headers = tny_simple_list_new ();
 	TnyIterator *iter;
 
+	g_static_mutex_lock (priv->running_lock);
+	if (priv->is_running) {
+		priv->cancel_requested = TRUE;
+		priv->cancel_action = cancel_action;
+		g_static_mutex_unlock (priv->running_lock);
+		return;
+	}
+	g_static_mutex_unlock (priv->running_lock);
+	
+
 	g_static_rec_mutex_lock (priv->sending_lock);
 
 	g_static_mutex_lock (priv->running_lock);
@@ -1532,6 +1564,9 @@ tny_camel_send_queue_instance_init (GTypeInstance *instance, gpointer g_class)
 	priv->cur_i = 0;
 	priv->trans_account = NULL;
 
+	priv->cancel_requested = FALSE;
+	priv->cancel_action = TNY_SEND_QUEUE_CANCEL_ACTION_SUSPEND;
+
 	return;
 }
 


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