]> source.dussan.org Git - gitea.git/commitdiff
Make cancel from CatFileBatch and CatFileBatchCheck wait for the command to end ...
authorzeripath <art27@cantab.net>
Tue, 20 Jul 2021 21:52:19 +0000 (22:52 +0100)
committerGitHub <noreply@github.com>
Tue, 20 Jul 2021 21:52:19 +0000 (23:52 +0200)
* Make cancel from CatFileBatch and CatFileBatchCheck wait for the command to end (#16479)

Fix #16427 (again!)

* handle sharing violation error code

Signed-off-by: Andrew Thornton <art27@cantab.net>
modules/git/batch_reader.go
modules/util/remove.go

index bdf82bde8913dd132679c6c1f98e80c8bd1e0f5e..164e643812894e0357fe80a5e50ee7722da61f1a 100644 (file)
@@ -7,6 +7,7 @@ package git
 import (
        "bufio"
        "bytes"
+       "context"
        "io"
        "math"
        "strconv"
@@ -28,16 +29,20 @@ type WriteCloserError interface {
 func CatFileBatchCheck(repoPath string) (WriteCloserError, *bufio.Reader, func()) {
        batchStdinReader, batchStdinWriter := io.Pipe()
        batchStdoutReader, batchStdoutWriter := io.Pipe()
+       ctx, ctxCancel := context.WithCancel(DefaultContext)
+       closed := make(chan struct{})
        cancel := func() {
                _ = batchStdinReader.Close()
                _ = batchStdinWriter.Close()
                _ = batchStdoutReader.Close()
                _ = batchStdoutWriter.Close()
+               ctxCancel()
+               <-closed
        }
 
        go func() {
                stderr := strings.Builder{}
-               err := NewCommand("cat-file", "--batch-check").RunInDirFullPipeline(repoPath, batchStdoutWriter, &stderr, batchStdinReader)
+               err := NewCommandContext(ctx, "cat-file", "--batch-check").RunInDirFullPipeline(repoPath, batchStdoutWriter, &stderr, batchStdinReader)
                if err != nil {
                        _ = batchStdoutWriter.CloseWithError(ConcatenateError(err, (&stderr).String()))
                        _ = batchStdinReader.CloseWithError(ConcatenateError(err, (&stderr).String()))
@@ -45,6 +50,7 @@ func CatFileBatchCheck(repoPath string) (WriteCloserError, *bufio.Reader, func()
                        _ = batchStdoutWriter.Close()
                        _ = batchStdinReader.Close()
                }
+               close(closed)
        }()
 
        // For simplicities sake we'll use a buffered reader to read from the cat-file --batch-check
@@ -59,16 +65,20 @@ func CatFileBatch(repoPath string) (WriteCloserError, *bufio.Reader, func()) {
        // so let's create a batch stdin and stdout
        batchStdinReader, batchStdinWriter := io.Pipe()
        batchStdoutReader, batchStdoutWriter := nio.Pipe(buffer.New(32 * 1024))
+       ctx, ctxCancel := context.WithCancel(DefaultContext)
+       closed := make(chan struct{})
        cancel := func() {
                _ = batchStdinReader.Close()
                _ = batchStdinWriter.Close()
                _ = batchStdoutReader.Close()
                _ = batchStdoutWriter.Close()
+               ctxCancel()
+               <-closed
        }
 
        go func() {
                stderr := strings.Builder{}
-               err := NewCommand("cat-file", "--batch").RunInDirFullPipeline(repoPath, batchStdoutWriter, &stderr, batchStdinReader)
+               err := NewCommandContext(ctx, "cat-file", "--batch").RunInDirFullPipeline(repoPath, batchStdoutWriter, &stderr, batchStdinReader)
                if err != nil {
                        _ = batchStdoutWriter.CloseWithError(ConcatenateError(err, (&stderr).String()))
                        _ = batchStdinReader.CloseWithError(ConcatenateError(err, (&stderr).String()))
@@ -76,6 +86,7 @@ func CatFileBatch(repoPath string) (WriteCloserError, *bufio.Reader, func()) {
                        _ = batchStdoutWriter.Close()
                        _ = batchStdinReader.Close()
                }
+               close(closed)
        }()
 
        // For simplicities sake we'll us a buffered reader to read from the cat-file --batch
index 754f3b7c1174db06fa07a48292a4807e7de04973..d05ee9fe4afa2cad4d6730364f35cbd40d8f77ec 100644 (file)
@@ -6,10 +6,13 @@ package util
 
 import (
        "os"
+       "runtime"
        "syscall"
        "time"
 )
 
+const windowsSharingViolationError syscall.Errno = 32
+
 // Remove removes the named file or (empty) directory with at most 5 attempts.
 func Remove(name string) error {
        var err error
@@ -25,6 +28,12 @@ func Remove(name string) error {
                        continue
                }
 
+               if unwrapped == windowsSharingViolationError && runtime.GOOS == "windows" {
+                       // try again
+                       <-time.After(100 * time.Millisecond)
+                       continue
+               }
+
                if unwrapped == syscall.ENOENT {
                        // it's already gone
                        return nil
@@ -48,6 +57,12 @@ func RemoveAll(name string) error {
                        continue
                }
 
+               if unwrapped == windowsSharingViolationError && runtime.GOOS == "windows" {
+                       // try again
+                       <-time.After(100 * time.Millisecond)
+                       continue
+               }
+
                if unwrapped == syscall.ENOENT {
                        // it's already gone
                        return nil
@@ -71,6 +86,12 @@ func Rename(oldpath, newpath string) error {
                        continue
                }
 
+               if unwrapped == windowsSharingViolationError && runtime.GOOS == "windows" {
+                       // try again
+                       <-time.After(100 * time.Millisecond)
+                       continue
+               }
+
                if i == 0 && os.IsNotExist(err) {
                        return err
                }