[geary/mjog/imap-command-cancellation: 5/6] Geary.Imap.Command: Improve cancelled-before send handling




commit a1b0547e67e77f0b10fb6877512599c6d790fdf6
Author: Michael Gratton <mike vee net>
Date:   Wed Sep 2 11:07:58 2020 +1000

    Geary.Imap.Command: Improve cancelled-before send handling
    
    Add `cancelled_before_send` method to support explicitly cancelling the
    command before it was sent, so that `wait_until_complete` does not end
    up waiting forever when this happens. Call the new method from
    `ClientConnection` as required.

 src/engine/imap/command/imap-command.vala          | 40 +++++++++++++++-------
 .../imap/transport/imap-client-connection.vala     |  2 ++
 2 files changed, 30 insertions(+), 12 deletions(-)
---
diff --git a/src/engine/imap/command/imap-command.vala b/src/engine/imap/command/imap-command.vala
index 702ce1af8..caa40e511 100644
--- a/src/engine/imap/command/imap-command.vala
+++ b/src/engine/imap/command/imap-command.vala
@@ -92,7 +92,7 @@ public abstract class Geary.Imap.Command : BaseObject {
     private Geary.Nonblocking.Semaphore complete_lock =
         new Geary.Nonblocking.Semaphore();
 
-    private ImapError? cancelled_cause = null;
+    private GLib.Error? cancelled_cause = null;
 
     private Geary.Nonblocking.Spinlock? literal_spinlock = null;
     private GLib.Cancellable? literal_cancellable = null;
@@ -277,6 +277,16 @@ public abstract class Geary.Imap.Command : BaseObject {
             throw this.cancelled_cause;
         }
 
+        // If everything above is fine, but sending was cancelled, it
+        // must have been cancelled after being sent. Throw an error
+        // indicating this specifically.
+        if (this.should_send != null &&
+            this.should_send.is_cancelled()) {
+            throw new GLib.IOError.CANCELLED(
+                "Command was cancelled after sending: %s", to_brief_string()
+            );
+        }
+
         check_has_status();
 
         // Since this is part of the public API, perform a strict
@@ -288,15 +298,6 @@ public abstract class Geary.Imap.Command : BaseObject {
                 this.status.to_string()
             );
         }
-
-        // If everything else looks fine, but sending was cancelled,
-        // throw an error here so the caller knows that was the case.
-        if (this.should_send != null &&
-            this.should_send.is_cancelled()) {
-            throw new GLib.IOError.CANCELLED(
-                "Sent command was cancelled: %s", to_brief_string()
-            );
-        }
     }
 
     public virtual string to_string() {
@@ -332,12 +333,27 @@ public abstract class Geary.Imap.Command : BaseObject {
     }
 
     /**
-     * Cancels this command due to a network or server disconnect.
+     * Marks this command as being cancelled before being sent.
      *
      * When this method is called, all locks will be released,
      * including {@link wait_until_complete}, which will then throw a
      * `GLib.IOError.CANCELLED` error.
      */
+    internal virtual void cancelled_before_send() {
+        cancel(
+            new GLib.IOError.CANCELLED(
+                "Command was cancelled before sending: %s", to_brief_string()
+            )
+        );
+    }
+
+    /**
+     * Cancels this command due to a network or server disconnect.
+     *
+     * When this method is called, all locks will be released,
+     * including {@link wait_until_complete}, which will then throw a
+     * `ImapError.NOT_CONNECTED` error.
+     */
     internal virtual void disconnected(string reason) {
         cancel(new ImapError.NOT_CONNECTED("%s: %s", to_brief_string(), reason));
     }
@@ -406,7 +422,7 @@ public abstract class Geary.Imap.Command : BaseObject {
         }
     }
 
-    private void cancel(ImapError cause) {
+    private void cancel(GLib.Error cause) {
         stop_serialisation();
         this.cancelled_cause = cause;
         this.response_timer.reset();
diff --git a/src/engine/imap/transport/imap-client-connection.vala 
b/src/engine/imap/transport/imap-client-connection.vala
index debb843db..390984e94 100644
--- a/src/engine/imap/transport/imap-client-connection.vala
+++ b/src/engine/imap/transport/imap-client-connection.vala
@@ -265,6 +265,7 @@ public class Geary.Imap.ClientConnection : BaseObject, Logging.Source {
         check_connection();
         if (new_command.should_send != null &&
             new_command.should_send.is_cancelled()) {
+            new_command.cancelled_before_send();
             throw new GLib.IOError.CANCELLED(
                 "Not queuing command, sending is cancelled: %s",
                 new_command.to_brief_string()
@@ -437,6 +438,7 @@ public class Geary.Imap.ClientConnection : BaseObject, Logging.Source {
         throws GLib.Error {
         if (command.should_send != null &&
             command.should_send.is_cancelled()) {
+            command.cancelled_before_send();
             throw new GLib.IOError.CANCELLED(
                 "Not sending command, sending is cancelled: %s",
                 command.to_brief_string()


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