Commit 430cccea authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

splice: empty splice.Pair by splicing into /dev/null

parent cfefa3d5
......@@ -35,3 +35,14 @@ func (p *Pair) WriteTo(fd uintptr, n int) (int, error) {
}
return int(m), err
}
const _SPLICE_F_NONBLOCK = 0x2
func (p *Pair) discard() {
_, err := syscall.Splice(p.r, nil, int(devNullFD), nil, int(p.size), _SPLICE_F_NONBLOCK)
if err == syscall.EAGAIN {
// all good.
} else if err != nil {
panic(err)
}
}
......@@ -6,7 +6,6 @@ package splice
import (
"sync"
"syscall"
)
var splicePool *pairPool
......@@ -33,7 +32,7 @@ func Used() int {
return splicePool.used()
}
// Return pipe pair to pool
// Done returns the pipe pair to pool.
func Done(p *Pair) {
splicePool.done(p)
}
......@@ -93,25 +92,8 @@ func (pp *pairPool) get() (p *Pair, err error) {
return newSplicePair()
}
var discardBuffer [32 * 1024]byte
func discardAll(fd int) {
buf := discardBuffer[:]
r := 0
for {
n, _ := syscall.Read(fd, buf)
if n > 0 {
r += n
}
if n < len(buf) {
break
}
}
}
func (pp *pairPool) done(p *Pair) {
discardAll(p.r)
p.discard()
pp.Lock()
pp.usedCount--
......
......@@ -30,6 +30,9 @@ func MaxPipeSize() int {
// Since Linux 2.6.11, the pipe capacity is 65536 bytes.
const DefaultPipeSize = 16 * 4096
// We empty pipes by splicing to /dev/null.
var devNullFD uintptr
func init() {
content, err := ioutil.ReadFile("/proc/sys/fs/pipe-max-size")
if err != nil {
......@@ -48,6 +51,13 @@ func init() {
resizable = resizable && (errNo == 0)
r.Close()
w.Close()
fd, err := syscall.Open("/dev/null", os.O_WRONLY, 0)
if err != nil {
log.Panicf("splice: %v", err)
}
devNullFD = uintptr(fd)
}
// copy & paste from syscall.
......
......@@ -12,6 +12,7 @@ import (
func TestPairSize(t *testing.T) {
p, _ := Get()
defer Done(p)
p.MaxGrow()
b := make([]byte, p.Cap()+100)
for i := range b {
......@@ -30,3 +31,20 @@ func TestPairSize(t *testing.T) {
}
}
func TestDiscard(t *testing.T) {
p, _ := Get()
defer Done(p)
if _, err := p.Write([]byte("hello")); err != nil {
t.Fatalf("Write: %v", err)
}
p.discard()
var b [1]byte
n, err := p.Read(b[:])
if n != -1 {
t.Fatalf("Read: got (%d, %v) want (-1, EAGAIN)", n, err)
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment