[lxc-devel] [lxd/master] Improve cancellation handling in client

stgraber on Github lxc-bot at linuxcontainers.org
Fri Nov 2 04:09:50 UTC 2018


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 301 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20181102/11ca106f/attachment.bin>
-------------- next part --------------
From 8165c24cce7f27d1df3ce45c3355cb2014449dd6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Thu, 1 Nov 2018 23:29:28 -0400
Subject: [PATCH 1/2] lxc: Switch all progress op handling to cancelable
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Closes #5233

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 lxc/action.go         |  7 +++++--
 lxc/copy.go           |  2 +-
 lxc/image.go          |  3 ++-
 lxc/import.go         |  4 +++-
 lxc/storage_volume.go |  3 ++-
 lxc/utils/cancel.go   | 29 ++++++++++++++++++++++++++---
 6 files changed, 39 insertions(+), 9 deletions(-)

diff --git a/lxc/action.go b/lxc/action.go
index 9c74fe668e..98c811f825 100644
--- a/lxc/action.go
+++ b/lxc/action.go
@@ -189,12 +189,15 @@ func (c *cmdAction) doAction(action string, conf *config.Config, nameArg string)
 		return err
 	}
 
-	err = op.Wait()
-	progress.Done("")
+	// Wait for operation to finish
+	err = utils.CancelableWait(op, &progress)
 	if err != nil {
+		progress.Done("")
 		return fmt.Errorf("%s\n"+i18n.G("Try `lxc info --show-log %s` for more info"), err, nameArg)
 	}
 
+	progress.Done("")
+
 	return nil
 }
 
diff --git a/lxc/copy.go b/lxc/copy.go
index eef1b28be6..f34b05d74e 100644
--- a/lxc/copy.go
+++ b/lxc/copy.go
@@ -323,7 +323,7 @@ func (c *cmdCopy) copyContainer(conf *config.Config, sourceResource string,
 	}
 
 	// Wait for the copy to complete
-	err = op.Wait()
+	err = utils.CancelableWait(op, &progress)
 	if err != nil {
 		progress.Done("")
 		return err
diff --git a/lxc/image.go b/lxc/image.go
index 5a603e4eaa..9a6825a381 100644
--- a/lxc/image.go
+++ b/lxc/image.go
@@ -749,7 +749,8 @@ func (c *cmdImageImport) Run(cmd *cobra.Command, args []string) error {
 		return err
 	}
 
-	err = op.Wait()
+	// Wait for operation to finish
+	err = utils.CancelableWait(op, &progress)
 	if err != nil {
 		progress.Done("")
 		return err
diff --git a/lxc/import.go b/lxc/import.go
index 74d4bc0d19..6d2ea724d7 100644
--- a/lxc/import.go
+++ b/lxc/import.go
@@ -85,11 +85,13 @@ func (c *cmdImport) Run(cmd *cobra.Command, args []string) error {
 		return err
 	}
 
-	err = op.Wait()
+	// Wait for operation to finish
+	err = utils.CancelableWait(op, &progress)
 	if err != nil {
 		progress.Done("")
 		return err
 	}
+
 	progress.Done("")
 
 	return nil
diff --git a/lxc/storage_volume.go b/lxc/storage_volume.go
index 7f7733ea59..ce6038b01c 100644
--- a/lxc/storage_volume.go
+++ b/lxc/storage_volume.go
@@ -431,7 +431,8 @@ func (c *cmdStorageVolumeCopy) Run(cmd *cobra.Command, args []string) error {
 		return err
 	}
 
-	err = op.Wait()
+	// Wait for operation to finish
+	err = utils.CancelableWait(op, &progress)
 	if err != nil {
 		progress.Done("")
 		return err
diff --git a/lxc/utils/cancel.go b/lxc/utils/cancel.go
index 8b378db653..0b0a684288 100644
--- a/lxc/utils/cancel.go
+++ b/lxc/utils/cancel.go
@@ -11,7 +11,20 @@ import (
 )
 
 // CancelableWait waits for an operation and cancel it on SIGINT/SIGTERM
-func CancelableWait(op lxd.RemoteOperation, progress *ProgressRenderer) error {
+func CancelableWait(rawOp interface{}, progress *ProgressRenderer) error {
+	var op lxd.Operation
+	var rop lxd.RemoteOperation
+
+	// Check what type of operation we're dealing with
+	switch v := rawOp.(type) {
+	case lxd.Operation:
+		op = v
+	case lxd.RemoteOperation:
+		rop = v
+	default:
+		return fmt.Errorf("Invalid operation type for CancelableWait")
+	}
+
 	// Signal handling
 	chSignal := make(chan os.Signal)
 	signal.Notify(chSignal, os.Interrupt)
@@ -19,17 +32,27 @@ func CancelableWait(op lxd.RemoteOperation, progress *ProgressRenderer) error {
 	// Operation handling
 	chOperation := make(chan error)
 	go func() {
-		chOperation <- op.Wait()
+		if op != nil {
+			chOperation <- op.Wait()
+		} else {
+			chOperation <- rop.Wait()
+		}
 		close(chOperation)
 	}()
 
 	count := 0
 	for {
+		var err error
+
 		select {
 		case err := <-chOperation:
 			return err
 		case <-chSignal:
-			err := op.CancelTarget()
+			if op != nil {
+				err = op.Cancel()
+			} else {
+				err = rop.CancelTarget()
+			}
 			if err == nil {
 				return fmt.Errorf(i18n.G("Remote operation canceled by user"))
 			}

From 293ebe9aae481a365fce0b2492a3403060527f6d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Fri, 2 Nov 2018 00:08:55 -0400
Subject: [PATCH 2/2] client: Fix cancelation of image download
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 client/simplestreams_images.go | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/client/simplestreams_images.go b/client/simplestreams_images.go
index 7f67ad9554..ac2bae5a31 100644
--- a/client/simplestreams_images.go
+++ b/client/simplestreams_images.go
@@ -84,6 +84,11 @@ func (r *ProtocolSimpleStreams) GetImageFile(fingerprint string, req ImageFileRe
 
 		size, err := shared.DownloadFileSha256(r.http, r.httpUserAgent, req.ProgressHandler, req.Canceler, filename, url, sha256, target)
 		if err != nil {
+			// Handle cancelation
+			if err.Error() == "net/http: request canceled" {
+				return -1, err
+			}
+
 			// Try over https
 			url = fmt.Sprintf("%s/%s", r.httpHost, path)
 			size, err = shared.DownloadFileSha256(r.http, r.httpUserAgent, req.ProgressHandler, req.Canceler, filename, url, sha256, target)


More information about the lxc-devel mailing list