Skip to content
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

x/sync/singleflight: DoChan's returned channel leaks if runtime.Goexit called from passed in func #52557

Closed
jasdel opened this issue Apr 25, 2022 · 2 comments
Labels
FrozenDueToAge WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided.
Milestone

Comments

@jasdel
Copy link
Contributor

jasdel commented Apr 25, 2022

What version of Go are you using (go version)?

$ go version
go version go1.18 darwin/amd64
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c

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="/Users/jasdel/Library/Caches/go-build"
GOENV="/Users/jasdel/Library/Application Support/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOINSECURE=""
GOMODCACHE="/Users/jasdel/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/jasdel/go"
GOPRIVATE=""
GOPROXY="direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64"
GOVCS=""
GOVERSION="go1.18"
GCCGO="gccgo"
GOAMD64="v1"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/dev/null"
GOWORK=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -arch x86_64 -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/7f/ynvg_sjn7dqc9dxz23x5c8pr0000gs/T/go-build2562339688=/tmp/go-build -gno-record-gcc-switches -fno-common"

What did you do?

The following test case will timeout, because the channel returned by DoChan is never signaled when the func passed in calls runtime.Goexit. I noticed this while reviewing the DoChan implementation. DoChan spins off a goroutine for doCall. The spun off goroutine will exit due to runtime.Goexit being called. The Do method handles this case by bubbling up the runtime.Goexit call to the caller's goroutine.

go test -run TestSingleFlightDoChan_leak -timeout 5s .
package main

import (
	"runtime"
	"testing"

	"golang.org/x/sync/singleflight"
)

func TestSingleFlightDoChan_leak(t *testing.T) {
	var g singleflight.Group

	t.Log("starting Do")
	resCh := g.DoChan("key", func() (interface{}, error) {
		t.Log("DoChan task started")
		runtime.Goexit()

		panic("unreachable")
	})

	t.Log("waiting on DoChan's returned channel ...")

	res := <-resCh
	t.Logf("have result, %#v", res)
}

What did you expect to see?

I'd expect DoChan to not leak the channel, instead potentially bubbling up the runtime.Goexit occurred. Potentially exposing and/or returning errGoexit as the Result.Err value. Or, closing the channel, but DoChan documents that it will never close the channel, so that's probably a breaking change.

Forget has no impact on "leaked" DoChan channels.

There are test cases for Do's handling of runtime.Goexit, but not DoChan's.

What did you see instead?

When the func given to DoChan calls runtime.Goexit, the channel returned by DoChan never has a Result message put on it, nor closed. Behavior of runtime.Goexit is also undocumented in in singleflight in general.

@gopherbot gopherbot added this to the Unreleased milestone Apr 25, 2022
@jasdel jasdel changed the title x/sync/singlflight: DoChan's returned channel leaks if runtime.Goexit called from passed in func ex/sync/singleflight: DoChan's returned channel leaks if runtime.Goexit called from passed in func Apr 25, 2022
@jasdel jasdel changed the title ex/sync/singleflight: DoChan's returned channel leaks if runtime.Goexit called from passed in func x/sync/singleflight: DoChan's returned channel leaks if runtime.Goexit called from passed in func Apr 25, 2022
@ianlancetaylor
Copy link
Contributor

I don't understand what we can actually do to fix this. I don't see any way to inform the goroutine waiting on the channel that no value is forthcoming.

@ianlancetaylor ianlancetaylor added the WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided. label Apr 25, 2022
@gopherbot
Copy link

Timed out in state WaitingForInfo. Closing.

(I am just a bot, though. Please speak up if this is a mistake or you have the requested information.)

@golang golang locked and limited conversation to collaborators May 25, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided.
Projects
None yet
Development

No branches or pull requests

3 participants