Close piped processes on cancellation
This commit is contained in:
@@ -51,6 +51,9 @@ func (reader *BlobReader) Read(ctx context.Context, objectID string) ([]byte, er
|
||||
|
||||
reader.mu.Lock()
|
||||
defer reader.mu.Unlock()
|
||||
if err := ctx.Err(); err != nil {
|
||||
return nil, fmt.Errorf("read blob %s: %w", objectID, err)
|
||||
}
|
||||
if reader.terminal != nil {
|
||||
return nil, reader.terminal
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
@@ -156,6 +157,46 @@ exec sleep 60`)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBlobReaderCanceledQueuedReadKeepsSessionUsable(t *testing.T) {
|
||||
fixture := newRemoteFixture(t)
|
||||
object := gitText(t, fixture.work, "rev-parse", "HEAD:source.txt")
|
||||
reader := NewBlobReader(t.Context(), fixture.work)
|
||||
defer reader.Close()
|
||||
if body, err := reader.Read(t.Context(), object); err != nil || string(body) != "candidate" {
|
||||
t.Fatalf("first read = %q, %v", body, err)
|
||||
}
|
||||
reader.mu.Lock()
|
||||
ctx, cancel := context.WithCancel(t.Context())
|
||||
observed := make(chan struct{})
|
||||
queued := &observedContext{Context: ctx, observed: observed}
|
||||
result := make(chan error, 1)
|
||||
go func() {
|
||||
_, err := reader.Read(queued, object)
|
||||
result <- err
|
||||
}()
|
||||
<-observed
|
||||
cancel()
|
||||
reader.mu.Unlock()
|
||||
if err := <-result; !errors.Is(err, context.Canceled) {
|
||||
t.Fatalf("queued read error = %v", err)
|
||||
}
|
||||
if body, err := reader.Read(t.Context(), object); err != nil || string(body) != "candidate" {
|
||||
t.Fatalf("later read = %q, %v", body, err)
|
||||
}
|
||||
}
|
||||
|
||||
type observedContext struct {
|
||||
context.Context
|
||||
once sync.Once
|
||||
observed chan struct{}
|
||||
}
|
||||
|
||||
func (ctx *observedContext) Err() error {
|
||||
err := ctx.Context.Err()
|
||||
ctx.once.Do(func() { close(ctx.observed) })
|
||||
return err
|
||||
}
|
||||
|
||||
func TestBlobReaderPreservesGitFailureAndStderr(t *testing.T) {
|
||||
installFakeGit(t, `printf 'fixture Git failure\n' >&2
|
||||
exit 23`)
|
||||
|
||||
Reference in New Issue
Block a user