Deflake SendFileTest_Shutdown.

The sendfile syscall's backing doSplice contained a race with regard to
blocking. If the first attempt failed with syserror.ErrWouldBlock and then
the blocking file became ready before registering a waiter, we would just
return the ErrWouldBlock (even if we were supposed to block).

PiperOrigin-RevId: 254114432
This commit is contained in:
Ian Gudger
2019-06-19 18:40:54 -07:00
committed by gVisor bot
parent c2d87d5d7c
commit 7e49515696
+7 -2
View File
@@ -48,12 +48,12 @@ func doSplice(t *kernel.Task, outFile, inFile *fs.File, opts fs.SpliceOpts, nonB
if ch == nil {
ch = make(chan struct{}, 1)
}
if !inW && inFile.Readiness(EventMaskRead) == 0 && !inFile.Flags().NonBlocking {
if !inW && !inFile.Flags().NonBlocking {
w, _ := waiter.NewChannelEntry(ch)
inFile.EventRegister(&w, EventMaskRead)
defer inFile.EventUnregister(&w)
inW = true // Registered.
} else if !outW && outFile.Readiness(EventMaskWrite) == 0 && !outFile.Flags().NonBlocking {
} else if !outW && !outFile.Flags().NonBlocking {
w, _ := waiter.NewChannelEntry(ch)
outFile.EventRegister(&w, EventMaskWrite)
defer outFile.EventUnregister(&w)
@@ -65,6 +65,11 @@ func doSplice(t *kernel.Task, outFile, inFile *fs.File, opts fs.SpliceOpts, nonB
break
}
if (!inW || inFile.Readiness(EventMaskRead) != 0) && (!outW || outFile.Readiness(EventMaskWrite) != 0) {
// Something became ready, try again without blocking.
continue
}
// Block until there's data.
if err = t.Block(ch); err != nil {
break