Commit b5c46276 authored by Brandon Duffany's avatar Brandon Duffany Committed by Han-Wen Nienhuys

Lazily init /dev/null fd

Fixes an issue that the init() func in splice.go panics if
/dev is not yet mounted.

This allows supporting go-based init binaries which set up all the
filesystems on the machine, including both /dev as well as
FUSE-mounted dirs.

Change-Id: I74dab18effe4df410689ae7a2ef43670fcab7bd8
parent 7b4f97c3
...@@ -40,7 +40,7 @@ func (p *Pair) WriteTo(fd uintptr, n int) (int, error) { ...@@ -40,7 +40,7 @@ func (p *Pair) WriteTo(fd uintptr, n int) (int, error) {
const _SPLICE_F_NONBLOCK = 0x2 const _SPLICE_F_NONBLOCK = 0x2
func (p *Pair) discard() { func (p *Pair) discard() {
_, err := syscall.Splice(p.r, nil, int(devNullFD), nil, int(p.size), _SPLICE_F_NONBLOCK) _, err := syscall.Splice(p.r, nil, devNullFD(), nil, int(p.size), _SPLICE_F_NONBLOCK)
if err == syscall.EAGAIN { if err == syscall.EAGAIN {
// all good. // all good.
} else if err != nil { } else if err != nil {
......
...@@ -11,6 +11,7 @@ import ( ...@@ -11,6 +11,7 @@ import (
"io/ioutil" "io/ioutil"
"log" "log"
"os" "os"
"sync"
"syscall" "syscall"
) )
...@@ -30,8 +31,10 @@ func MaxPipeSize() int { ...@@ -30,8 +31,10 @@ func MaxPipeSize() int {
// Since Linux 2.6.11, the pipe capacity is 65536 bytes. // Since Linux 2.6.11, the pipe capacity is 65536 bytes.
const DefaultPipeSize = 16 * 4096 const DefaultPipeSize = 16 * 4096
// We empty pipes by splicing to /dev/null. var (
var devNullFD uintptr devNullFDOnce sync.Once
devNullFDValue int
)
func init() { func init() {
content, err := ioutil.ReadFile("/proc/sys/fs/pipe-max-size") content, err := ioutil.ReadFile("/proc/sys/fs/pipe-max-size")
...@@ -51,13 +54,18 @@ func init() { ...@@ -51,13 +54,18 @@ func init() {
resizable = resizable && (errNo == 0) resizable = resizable && (errNo == 0)
r.Close() r.Close()
w.Close() w.Close()
}
fd, err := syscall.Open("/dev/null", os.O_WRONLY, 0) // We empty pipes by splicing to /dev/null.
if err != nil { func devNullFD() int {
log.Panicf("splice: %v", err) devNullFDOnce.Do(func() {
} fd, err := syscall.Open("/dev/null", os.O_WRONLY, 0)
if err != nil {
devNullFD = uintptr(fd) panic(fmt.Sprintf("failed to open /dev/null: %s", err))
}
devNullFDValue = fd
})
return devNullFDValue
} }
// copy & paste from syscall. // copy & paste from syscall.
......
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