Skip to content

os: Read() blocking on named pipe despite O_NONBLOCK #66239

@poundifdef

Description

@poundifdef

Go version

go version go1.22.1 darwin/arm64

Output of go env in your module/workspace:

GO111MODULE='on'
GOARCH='arm64'
GOBIN=''
GOCACHE='/Users/jgoel/Library/Caches/go-build'
GOENV='/Users/jgoel/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMODCACHE='/Users/jgoel/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='darwin'
GOPATH='/Users/jgoel/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/opt/homebrew/Cellar/go/1.22.1/libexec'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/opt/homebrew/Cellar/go/1.22.1/libexec/pkg/tool/darwin_arm64'
GOVCS=''
GOVERSION='go1.22.1'
GCCGO='gccgo'
AR='ar'
CC='cc'
CXX='c++'
CGO_ENABLED='1'
GOMOD='/Users/jgoel/github/scratchdata/scripts/duckdbcopy/go.mod'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/6y/xyh8yvqx7dx_ftw31n218m940000gn/T/go-build1801743762=/tmp/go-build -gno-record-gcc-switches -fno-common'

What did you do?

When calling os.Read() on a named pipe with O_NONBLOCK, that call will sometimes block. I only see the the bug on my M1 Mac. When I run this code in Linux or in the go playground, I do not see the bug. Here is a full program to reproduce:

https://go.dev/play/p/Ryc4jmgag3t

What did you see happen?

jgoel@jgoels-Air bug % go run main.go
2024/03/10 21:37:12 Opening pipe <nil>
2024/03/10 21:37:12 About to read...
2024/03/10 21:37:12 Read from pipe 5 <nil> Hello
2024/03/10 21:37:12 About to read...
2024/03/10 21:37:13 Read from pipe 5 <nil> Hello
2024/03/10 21:37:13 About to read...
2024/03/10 21:37:14 Read from pipe 5 <nil> Hello
2024/03/10 21:37:14 About to read...
2024/03/10 21:37:15 Read from pipe 5 <nil> Hello
2024/03/10 21:37:15 About to read...
2024/03/10 21:37:16 Read from pipe 5 <nil> Hello
2024/03/10 21:37:16 About to read...
2024/03/10 21:37:17 Writer closed pipe <nil>

(...program hangs indefinitely blocking on Read() when it should loop infinitely...)

What did you expect to see?

I expected to see the same output as above, plus the following lines looped infinitely:

2024/03/11 01:35:04 About to read...
2024/03/11 01:35:04 Read from pipe 0 EOF ol
2024/03/11 01:35:04 About to read...

This program does behave the way I'd like if I make any of these changes:

  1. If I replace os.OpenFile() and os.File.Read() with syscall.Open() and syscall.Read(), then the program does work as expected on Mac. It does not block, and it loops infinitely. Here is an example: https://go.dev/play/p/cflSTMW3RCk
  2. If I remove the call to time.Sleep() in the goroutine, then the program also works as expected.
  3. Finally, the original program works as expected on Linux. I only observe the blocking Read() on Mac.

Metadata

Metadata

Assignees

Labels

FrozenDueToAgeNeedsFixThe path to resolution is known, but the work has not been done.OS-Darwincompiler/runtimeIssues related to the Go compiler and/or runtime.

Type

No type

Projects

Status

Done

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions