From 53aac50a1c027397c9f0fd6c13f840adbbd36f21 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sat, 27 Jul 2019 19:48:37 -0700 Subject: [PATCH] open /dev/fuse in blocking mode so the runtime does not use a poller MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit /dev/fuse is not pollable. Go ≥ 1.13 starts reporting this on Read(). --- mount_linux.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mount_linux.go b/mount_linux.go index 0decf0b..ce83d9f 100644 --- a/mount_linux.go +++ b/mount_linux.go @@ -126,10 +126,14 @@ var mountflagopts = map[string]func(uintptr) uintptr{ var errFallback = errors.New("sentinel: fallback to fusermount(1)") func directmount(dir string, cfg *MountConfig) (*os.File, error) { - dev, err := os.OpenFile("/dev/fuse", os.O_RDWR, 0644) + // We use syscall.Open + os.NewFile instead of os.OpenFile so that the file + // is opened in blocking mode. When opened in non-blocking mode, the Go + // runtime tries to use poll(2), which does not work with /dev/fuse. + fd, err := syscall.Open("/dev/fuse", syscall.O_RDWR, 0644) if err != nil { return nil, errFallback } + dev := os.NewFile(uintptr(fd), "/dev/fuse") // As per libfuse/fusermount.c:847: https://bit.ly/2SgtWYM#L847 data := fmt.Sprintf("fd=%d,rootmode=40000,user_id=%d,group_id=%d", dev.Fd(), os.Getuid(), os.Getgid())