New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

os: OpenFile issue on darwin: 100% CPU on pty master read #22099

Open
creack opened this Issue Oct 1, 2017 · 1 comment

Comments

Projects
None yet
2 participants
@creack
Contributor

creack commented Oct 1, 2017

Go version: go version go1.9 darwin/amd64

os.OpenFile calls os.newFile with pollable always true. (

return newFile(uintptr(r), name, true), nil
)

On darwin, open /dev/ptmx fails to set the non-blocking flag, however, the subsequent slaves work fine. (

go/src/os/file_unix.go

Lines 105 to 119 in 9f7fd89

if err := f.pfd.Init("file", pollable); err != nil {
// An error here indicates a failure to register
// with the netpoll system. That can happen for
// a file descriptor that is not supported by
// epoll/kqueue; for example, disk files on
// GNU/Linux systems. We assume that any real error
// will show up in later I/O.
} else if pollable {
// We successfully registered with netpoll, so put
// the file into nonblocking mode.
if err := syscall.SetNonblock(fdi, true); err == nil {
f.nonblock = true
}
}
)

My guess is that having the slave in non-blocking mode is the reason why read on the master takes 100% CPU.

Details of the issue: kr/pty#52
Quickfix: kr/pty#53

Is it expected always set the poller when using os.OpenFile? Maybe we should take a look at the flags and see if there is O_NONBLOCK instead of forcing it or maybe introduce a new flag to toggle the poller?

To reproduce on darwin: https://play.golang.org/p/rq8pJGL3ey

@ianlancetaylor ianlancetaylor added this to the Go1.10 milestone Oct 1, 2017

@ianlancetaylor

This comment has been minimized.

Contributor

ianlancetaylor commented Oct 1, 2017

On Darwin we use the poller when the operating system permits us to use kevent to pass the file descriptor to a kqueue. When there is no error there, we put the descriptor into non-blocking mode and do I/O using kqueue. It sounds like that doesn't work on Darwin for /dev/ptmx, which sounds like a bug in Darwin.

The workaround of using syscall.Open seems fine for a special purpose case like this. I'm certainly open to fixing this in the standard library if someone can figure out a good fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment