From b360527931465b6aba6c4a7da94e016f307ae558 Mon Sep 17 00:00:00 2001
From: Nick Craig-Wood <nick@craig-wood.com>
Date: Mon, 26 Jun 2017 11:58:12 +0100
Subject: [PATCH] mount: fix hang on errored upload

In certain circumstances if an upload failed then the mount could hang
indefinitely. This was fixed by closing the read pipe after the Put
completed.  This will cause the write side to return a pipe closed
error fixing the hang.

Fixes #1498
---
 cmd/mountlib/write.go | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/cmd/mountlib/write.go b/cmd/mountlib/write.go
index 66cc50d6c..951712b0e 100644
--- a/cmd/mountlib/write.go
+++ b/cmd/mountlib/write.go
@@ -13,7 +13,6 @@ type WriteFileHandle struct {
 	mu          sync.Mutex
 	closed      bool // set if handle has been closed
 	remote      string
-	pipeReader  *io.PipeReader
 	pipeWriter  *io.PipeWriter
 	o           fs.Object
 	result      chan error
@@ -39,10 +38,16 @@ func newWriteFileHandle(d *Dir, f *File, src fs.ObjectInfo) (*WriteFileHandle, e
 		file:   f,
 		hash:   hash,
 	}
-	fh.pipeReader, fh.pipeWriter = io.Pipe()
-	r := fs.NewAccountSizeName(fh.pipeReader, 0, src.Remote()).WithBuffer() // account the transfer
+	var pipeReader *io.PipeReader
+	pipeReader, fh.pipeWriter = io.Pipe()
 	go func() {
+		r := fs.NewAccountSizeName(pipeReader, 0, src.Remote()).WithBuffer() // account the transfer
 		o, err := d.f.Put(r, src)
+		if err != nil {
+			fs.Errorf(fh.remote, "WriteFileHandle.New Put failed: %v", err)
+		}
+		// Close the Account and thus the pipeReader so the pipeWriter fails with ErrClosedPipe
+		_ = r.Close()
 		fh.o = o
 		fh.result <- err
 	}()
@@ -120,14 +125,10 @@ func (fh *WriteFileHandle) close() error {
 	fh.file.addWriters(-1)
 	writeCloseErr := fh.pipeWriter.Close()
 	err := <-fh.result
-	readCloseErr := fh.pipeReader.Close()
 	if err == nil {
 		fh.file.setObject(fh.o)
 		err = writeCloseErr
 	}
-	if err == nil {
-		err = readCloseErr
-	}
 	if err == nil && fh.hash != nil {
 		for hashType, srcSum := range fh.hash.Sums() {
 			dstSum, err := fh.o.Hash(hashType)