mirror of
https://github.com/golang/go
synced 2024-11-27 04:01:19 -07:00
internal/poll: add SPLICE_F_NONBLOCK flag for splice to avoid inconsistency with O_NONBLOCK
For #59041 Details: https://github.com/golang/go/issues/59041#issuecomment-1766610087 Change-Id: Id3fc1df6d86b7c4cc383d09f9465fa8f4cc2a559 Reviewed-on: https://go-review.googlesource.com/c/go/+/536015 Reviewed-by: Bryan Mills <bcmills@google.com> Reviewed-by: Ian Lance Taylor <iant@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Ian Lance Taylor <iant@google.com>
This commit is contained in:
parent
f3a2459caa
commit
40cdf69fc9
@ -13,6 +13,12 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
// spliceNonblock doesn't make the splice itself necessarily nonblocking
|
||||
// (because the actual file descriptors that are spliced from/to may block
|
||||
// unless they have the O_NONBLOCK flag set), but it makes the splice pipe
|
||||
// operations nonblocking.
|
||||
spliceNonblock = 0x2
|
||||
|
||||
// maxSpliceSize is the maximum amount of data Splice asks
|
||||
// the kernel to move in a single call to splice(2).
|
||||
// We use 1MB as Splice writes data through a pipe, and 1MB is the default maximum pipe buffer size,
|
||||
@ -89,7 +95,11 @@ func spliceDrain(pipefd int, sock *FD, max int) (int, error) {
|
||||
return 0, err
|
||||
}
|
||||
for {
|
||||
n, err := splice(pipefd, sock.Sysfd, max, 0)
|
||||
// In theory calling splice(2) with SPLICE_F_NONBLOCK could end up an infinite loop here,
|
||||
// because it could return EAGAIN ceaselessly when the write end of the pipe is full,
|
||||
// but this shouldn't be a concern here, since the pipe buffer must be sufficient for
|
||||
// this data transmission on the basis of the workflow in Splice.
|
||||
n, err := splice(pipefd, sock.Sysfd, max, spliceNonblock)
|
||||
if err == syscall.EINTR {
|
||||
continue
|
||||
}
|
||||
@ -127,7 +137,14 @@ func splicePump(sock *FD, pipefd int, inPipe int) (int, error) {
|
||||
}
|
||||
written := 0
|
||||
for inPipe > 0 {
|
||||
n, err := splice(sock.Sysfd, pipefd, inPipe, 0)
|
||||
// In theory calling splice(2) with SPLICE_F_NONBLOCK could end up an infinite loop here,
|
||||
// because it could return EAGAIN ceaselessly when the read end of the pipe is empty,
|
||||
// but this shouldn't be a concern here, since the pipe buffer must contain inPipe size of
|
||||
// data on the basis of the workflow in Splice.
|
||||
n, err := splice(sock.Sysfd, pipefd, inPipe, spliceNonblock)
|
||||
if err == syscall.EINTR {
|
||||
continue
|
||||
}
|
||||
// Here, the condition n == 0 && err == nil should never be
|
||||
// observed, since Splice controls the write side of the pipe.
|
||||
if n > 0 {
|
||||
|
Loading…
Reference in New Issue
Block a user