Skip to content

Commit 400101a

Browse files
committed
[disk] drain any remaining data before Put returns
io.PipeWriter Write calls block until all the data written in the call is read from the corresponding io.PipeReader. If we don't read all that data, then the writing goroutine will block forever. The PipeWriter used in bytestream Write calls is intended to be consumed by disk.Put(), but if that returns early then there will be blocked writes. To un-block them, we should ensure that any remaining data is drained before disk.Put returns. Backport of #474
1 parent bb0d159 commit 400101a

File tree

1 file changed

+10
-2
lines changed

1 file changed

+10
-2
lines changed

cache/disk/disk.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,8 +223,15 @@ func (c *Cache) loadExistingFiles() error {
223223

224224
// Put stores a stream of `size` bytes from `r` into the cache.
225225
// If `hash` is not the empty string, and the contents don't match it,
226-
// a non-nil error is returned.
226+
// a non-nil error is returned. All data will be read from `r` before
227+
// this function returns.
227228
func (c *Cache) Put(kind cache.EntryKind, hash string, size int64, r io.Reader) (rErr error) {
229+
defer func() {
230+
if r != nil {
231+
_, _ = io.Copy(ioutil.Discard, r)
232+
}
233+
}()
234+
228235
if size < 0 {
229236
return fmt.Errorf("Invalid (negative) size: %d", size)
230237
}
@@ -237,7 +244,6 @@ func (c *Cache) Put(kind cache.EntryKind, hash string, size int64, r io.Reader)
237244
}
238245

239246
if kind == cache.CAS && size == 0 && hash == emptySha256 {
240-
io.Copy(ioutil.Discard, r)
241247
return nil
242248
}
243249

@@ -304,6 +310,8 @@ func (c *Cache) Put(kind cache.EntryKind, hash string, size int64, r io.Reader)
304310
return err
305311
}
306312

313+
r = nil // We read all the data from r.
314+
307315
if c.proxy != nil {
308316
rc, err := os.Open(tf.Name())
309317
if err != nil {

0 commit comments

Comments
 (0)