From b8acad4da091aa6f19d665b2b73711a029124476 Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Thu, 22 Sep 2022 21:52:18 +0200 Subject: [PATCH] rclone: return rclone error instead of canceled context When rclone fails during the connection setup this currently often results in a context canceled error. Replace this error with the exit code from rclone. --- internal/backend/rclone/backend.go | 11 ++++++++++- internal/backend/rclone/internal_test.go | 13 +++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/internal/backend/rclone/backend.go b/internal/backend/rclone/backend.go index df1d13d02..8a7c320cb 100644 --- a/internal/backend/rclone/backend.go +++ b/internal/backend/rclone/backend.go @@ -13,6 +13,7 @@ import ( "os" "os/exec" "sync" + "syscall" "time" "github.com/cenkalti/backoff/v4" @@ -244,7 +245,15 @@ func newBackend(cfg Config, lim limiter.Limiter) (*Backend, error) { // ignore subsequent errors _ = bg() _ = cmd.Process.Kill() - return nil, errors.Errorf("error talking HTTP to rclone: %v", err) + + // wait for rclone to exit + wg.Wait() + // try to return the program exit code if communication with rclone has failed + if be.waitResult != nil && (err == context.Canceled || errors.Is(err, io.ErrUnexpectedEOF) || errors.Is(err, syscall.EPIPE)) { + err = be.waitResult + } + + return nil, fmt.Errorf("error talking HTTP to rclone: %w", err) } debug.Log("HTTP status %q returned, moving instance to background", res.Status) diff --git a/internal/backend/rclone/internal_test.go b/internal/backend/rclone/internal_test.go index fe9a63d30..a606596bb 100644 --- a/internal/backend/rclone/internal_test.go +++ b/internal/backend/rclone/internal_test.go @@ -41,3 +41,16 @@ func TestRcloneExit(t *testing.T) { rtest.Assert(t, err != nil, "expected an error") } } + +// restic should detect rclone startup failures +func TestRcloneFailedStart(t *testing.T) { + cfg := NewConfig() + // exits with exit code 1 + cfg.Program = "false" + _, err := Open(cfg, nil) + var e *exec.ExitError + if !errors.As(err, &e) { + // unexpected error + rtest.OK(t, err) + } +}