Patch: avoid hangs on cancelling send queue
- From: José Dapena Paz <jdapena igalia com>
- To: tinymail-devel-list <tinymail-devel-list gnome org>
- Subject: Patch: avoid hangs on cancelling send queue
- Date: Wed, 01 Apr 2009 22:55:03 +0200
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]