Join GitHub today
GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.Sign up
os, runtime: Go 1.9 assumes epoll is non-blocking #21014
See extensive discussion on hanwen/go-fuse#165
After discussion with Heschi and Austin, we came up with the following explanation:
The poller was not implemented with the assumption it could block (and is wired especially into the runtime?). Hence, when it runs on a P, a blocking epoll call will prevent other goroutines on the same P from running. If one of these is either the read syscall that gets the POLL opcode, or the write syscall that returns ENOSYS, then the POLL opcode never gets processed, and the runtime deadlocks itself.
This is only a problem if the same program both issues epoll calls and responds to them, in other words, tests for FUSE filesystems, so this is probably not a showstopper for the Go 1.9 release.
We could kludge around this by having go-fuse issue our own epoll call (a blocking syscall); this would trigger a FUSE POLL opcode which we could respond to with ENOSYS preventing further poll problems. (does epoll work for directory file descriptors?)
I assume that the problem occurs in the call to the
While it seems clearly more likely when
If I understand the FUSE code correctly, which I probably don't, the FUSE code is running a goroutine that sits in
I think this would work if the FUSE daemon used
I haven't yet been able to think of a workable fix in the Go runtime.
If there is a way for the os package to detect that a file is on a FUSE filesystem, then we could avoid using the poller for that file. But I don't know of a way to do that.
FWIW, on Linux you can find out if a file is on FUSE by calling fstatfs on the fd, and checking the f_type field of the result. It does sound like a lot of overhead, since most files arent on FUSE, and some care is needed since fstatfs is also forwarded to FUSE, so you cannot call it from where you call epoll.