summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMilan Crha <mcrha@redhat.com>2016-01-26 15:14:37 +0100
committerMilan Crha <mcrha@redhat.com>2016-01-26 15:17:44 +0100
commit16736b1d6fb10e1862f8f32f726696efd8a41a03 (patch)
tree573b2134d55f339fb734c08cbcdf97e9ee0aff34
parent3153138001f678c00bd299852ed94c92ebdda431 (diff)
downloadevolution-data-server-16736b1d6fb10e1862f8f32f726696efd8a41a03.tar.gz
[IMAPx] Stop IDLE gracefully
My previous changes caused IDLE not to be stopped gracefully, which could cause several issues and side effects, for example if ever seen an error "Stream has outstanding operation" in UI, then it was one of the issues being caused by it.
-rw-r--r--camel/providers/imapx/camel-imapx-server.c91
1 files changed, 39 insertions, 52 deletions
diff --git a/camel/providers/imapx/camel-imapx-server.c b/camel/providers/imapx/camel-imapx-server.c
index b28c4be38..4c6b1d0db 100644
--- a/camel/providers/imapx/camel-imapx-server.c
+++ b/camel/providers/imapx/camel-imapx-server.c
@@ -5917,8 +5917,17 @@ imapx_server_idle_thread (gpointer user_data)
previous_timeout = imapx_server_set_connection_timeout (is->priv->connection, INACTIVITY_TIMEOUT_SECONDS + 60);
g_mutex_unlock (&is->priv->stream_lock);
- /* Blocks, until the DONE is issued or on inactivity timeout, error, ... */
- success = camel_imapx_server_process_command_sync (is, ic, _("Error running IDLE"), idle_cancellable, &local_error);
+ g_rec_mutex_lock (&is->priv->idle_lock);
+ if (is->priv->idle_stamp == itd->idle_stamp) {
+ g_rec_mutex_unlock (&is->priv->idle_lock);
+
+ /* Blocks, until the DONE is issued or on inactivity timeout, error, ... */
+ success = camel_imapx_server_process_command_sync (is, ic, _("Error running IDLE"), idle_cancellable, &local_error);
+
+ rather_disconnect = rather_disconnect || !success || g_cancellable_is_cancelled (idle_cancellable);
+ } else {
+ g_rec_mutex_unlock (&is->priv->idle_lock);
+ }
if (previous_timeout >= 0) {
g_mutex_lock (&is->priv->stream_lock);
@@ -5935,11 +5944,11 @@ imapx_server_idle_thread (gpointer user_data)
g_rec_mutex_unlock (&is->priv->idle_lock);
if (success)
- c (camel_imapx_server_get_tagprefix (is), "IDLE finished successfully");
+ c (camel_imapx_server_get_tagprefix (is), "IDLE finished successfully\n");
else if (local_error)
- c (camel_imapx_server_get_tagprefix (is), "IDLE finished with error: %s%s", local_error->message, rather_disconnect ? "; rather disconnect" : "");
+ c (camel_imapx_server_get_tagprefix (is), "IDLE finished with error: %s%s\n", local_error->message, rather_disconnect ? "; rather disconnect" : "");
else
- c (camel_imapx_server_get_tagprefix (is), "IDLE finished without error%s", rather_disconnect ? "; rather disconnect" : "");
+ c (camel_imapx_server_get_tagprefix (is), "IDLE finished without error%s\n", rather_disconnect ? "; rather disconnect" : "");
if (rather_disconnect) {
imapx_disconnect (is);
@@ -6141,64 +6150,42 @@ camel_imapx_server_stop_idle_sync (CamelIMAPXServer *is,
g_rec_mutex_unlock (&is->priv->idle_lock);
- if (idle_cancellable) {
- g_cancellable_cancel (idle_cancellable);
- g_object_unref (idle_cancellable);
- }
-
- if (idle_thread)
- g_thread_join (idle_thread);
-
if (idle_command) {
- CamelIMAPXCommand *ic;
- gint previous_timeout = -1;
- GError *local_error = NULL;
-
- g_return_val_if_fail (is->priv->current_command == NULL, FALSE);
-
- ic = camel_imapx_command_new (is, CAMEL_IMAPX_JOB_DONE, "DONE");
- ic->tag = idle_command->tag;
-
g_mutex_lock (&is->priv->stream_lock);
- /* Set the connection timeout to some short time, no need to wait for it for too long */
- if (is->priv->connection)
- previous_timeout = imapx_server_set_connection_timeout (is->priv->connection, 15);
- g_mutex_unlock (&is->priv->stream_lock);
-
- success = camel_imapx_server_process_command_sync (is, ic, _("Failed to issue DONE"), cancellable, &local_error);
+ if (is->priv->output_stream) {
+ gint previous_timeout = -1;
- if (previous_timeout >= 0) {
- g_mutex_lock (&is->priv->stream_lock);
+ /* Set the connection timeout to some short time, no need to wait for it for too long */
if (is->priv->connection)
- imapx_server_set_connection_timeout (is->priv->connection, previous_timeout);
- g_mutex_unlock (&is->priv->stream_lock);
- }
+ previous_timeout = imapx_server_set_connection_timeout (is->priv->connection, 5);
- camel_imapx_command_unref (ic);
- camel_imapx_command_unref (idle_command);
+ success = g_output_stream_flush (is->priv->output_stream, cancellable, error);
+ success = success && g_output_stream_write_all (is->priv->output_stream, "DONE\r\n", 6, NULL, cancellable, error);
+ success = success && g_output_stream_flush (is->priv->output_stream, cancellable, error);
- if (success)
- c (camel_imapx_server_get_tagprefix (is), "DONE finished successfully\n");
- else
- c (camel_imapx_server_get_tagprefix (is), "DONE finished with error: %s\n", local_error ? local_error->message : "Unknown error");
+ if (previous_timeout >= 0 && is->priv->connection)
+ imapx_server_set_connection_timeout (is->priv->connection, previous_timeout);
+ } else {
+ success = FALSE;
- if (!success) {
- GError *tmp = local_error;
+ /* This message won't get into UI. */
+ g_set_error_literal (error, CAMEL_IMAPX_SERVER_ERROR, CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT,
+ "Reconnect after couldn't issue DONE command");
+ }
+ g_mutex_unlock (&is->priv->stream_lock);
- local_error = NULL;
+ camel_imapx_command_unref (idle_command);
+ }
- g_set_error (
- &local_error, CAMEL_IMAPX_SERVER_ERROR, CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT,
- "Failed to finish IDLE with DONE: %s", tmp ? tmp->message : "Unknown error");
+ if ((!idle_command || !success) && idle_cancellable) {
+ g_cancellable_cancel (idle_cancellable);
+ }
- g_clear_error (&tmp);
- }
+ if (idle_cancellable)
+ g_object_unref (idle_cancellable);
- if (local_error) {
- g_propagate_error (error, local_error);
- success = FALSE;
- }
- }
+ if (idle_thread)
+ g_thread_join (idle_thread);
return success;
}