go: net: document that on some systems SetLinger causes conn.Close to block
What version of Go are you using (go version)?
$ go version go version go1.20.1 linux/amd64
Does this issue reproduce with the latest release?
Yes.
What operating system and processor architecture are you using (go env)?
go env Output
$ go env GO111MODULE="" GOARCH="amd64" GOBIN="" GOCACHE="/home/stephen/.cache/go-build" GOENV="/home/stephen/.config/go/env" GOEXE="" GOEXPERIMENT="" GOFLAGS="" GOHOSTARCH="amd64" GOHOSTOS="linux" GOINSECURE="" GOMODCACHE="/home/stephen/go/pkg/mod" GONOPROXY="" GONOSUMDB="" GOOS="linux" GOPATH="/home/stephen/go" GOPRIVATE="" GOPROXY="https://proxy.golang.org,direct" GOROOT="/usr/local/go" GOSUMDB="sum.golang.org" GOTMPDIR="" GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64" GOVCS="" GOVERSION="go1.20.1" GCCGO="gccgo" GOAMD64="v1" AR="ar" CC="gcc" CXX="g++" CGO_ENABLED="1" GOMOD="/dev/null" 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 -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build223210887=/tmp/go-build -gno-record-gcc-switches"
What did you do?
We added an explicit call to SetLinger(15) here: https://github.com/ava-labs/avalanchego/commit/1a2dca18d22a7a78e421e95dbdbe038287ee8361
What did you expect to see?
https://github.com/golang/go/blob/b94dc384cabf75e7e8703265cd80f5324f84b642/src/net/tcpsock.go#L161-L173 claims that providing SetLinger with a positive value will:
// If sec > 0, the data is sent in the background as with sec < 0. On // some operating systems after sec seconds have elapsed any remaining // unsent data may be discarded.
We expected for the OS to flush any outstanding data over the TCP stream in the background.
What did you see instead?
It doesn’t seem that the data is being sent in the backaground, but that conn.Close() may block until the specified timeout.
I don’t think this is actually unexpected for the behavior of SO_LINGER:
SO_LINGER Lingers on a close() if data is present. This option controls the action taken when unsent messages queue on a socket and close() is performed. If SO_LINGER is set, the system shall block the process during close() until it can transmit the data or until the time expires. If SO_LINGER is not specified, and close() is issued, the system handles the call in a way that allows the process to continue as quickly as possible. This option takes a linger structure, as defined in the <sys/socket.h> header, to specify the state of the option and linger interval.
However, I feel like the comment on SetLinger seems to contradict the man pages.
About this issue
- Original URL
- State: closed
- Created a year ago
- Comments: 17 (8 by maintainers)
Thank you for all the effort here. @StephenButtolph
Thanks. For me that program blocks for 15 seconds in the call to
syscall.Close, which is consistent with what you said earlier. I guess that Linux behaves that way, which I was not previously aware of. That makes it seems that there is no bug from Go’s perspective. There isn’t much that Go can do if the system call blocks.But I guess we can mention that in the
SetLingerdocs.