From fe3591bd8a96873abc98bb9d2d5c62f27efca3e9 Mon Sep 17 00:00:00 2001 From: berbreik Date: Sat, 11 Jan 2025 04:45:34 +0530 Subject: [PATCH 1/3] sync/errgroup: improve documentation for semaphore limit behavior Updated the documentation for `SetLimit` and `Go` functions in the `errgroup` package. the note clarifies the behavior when the semaphore limit is set to zero, which could lead to a deadlock if not handled properly. the updated documentation warns users to set a positive semaphore limit to avoid blocking goroutines and potential deadlock this change improves the clarity of API and helps users understand how to properly use the semaphore limit to prevent issues in concurrent execution Change-Id: Ie62acc38ef804b3590c04bddba00a3cce21e8cef Reviewed-on: https://go-review.googlesource.com/c/sync/+/642215 Reviewed-by: Michael Knyszek LUCI-TryBot-Result: Go LUCI Reviewed-by: Ian Lance Taylor Auto-Submit: Ian Lance Taylor --- errgroup/errgroup.go | 1 + 1 file changed, 1 insertion(+) diff --git a/errgroup/errgroup.go b/errgroup/errgroup.go index 948a3ee..b832259 100644 --- a/errgroup/errgroup.go +++ b/errgroup/errgroup.go @@ -118,6 +118,7 @@ func (g *Group) TryGo(f func() error) bool { // SetLimit limits the number of active goroutines in this group to at most n. // A negative value indicates no limit. +// A limit of zero will prevent any new goroutines from being added. // // Any subsequent call to the Go method will block until it can add an active // goroutine without exceeding the configured limit. From 960bf1fb13c616a491486fc6322e26fe0830eaf0 Mon Sep 17 00:00:00 2001 From: Gopher Robot Date: Fri, 14 Feb 2025 21:16:47 +0000 Subject: [PATCH 2/3] all: upgrade go directive to at least 1.23.0 [generated] By now Go 1.24.0 has been released, and Go 1.22 is no longer supported per the Go Release Policy (https://go.dev/doc/devel/release#policy). For golang/go#69095. [git-generate] (cd . && go get go@1.23.0 && go mod tidy && go fix ./... && go mod edit -toolchain=none) Change-Id: I7e3b1e073a0a64e82e2b9e49387d5da0afd9d58b Reviewed-on: https://go-review.googlesource.com/c/sync/+/649835 Reviewed-by: Dmitri Shuralyov Reviewed-by: Cherry Mui LUCI-TryBot-Result: Go LUCI Auto-Submit: Gopher Robot --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 74bd0ac..d30ac75 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,3 @@ module golang.org/x/sync -go 1.18 +go 1.23.0 From b637f27e40ad6e222f3d301cc113e635f0fa08be Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 4 Mar 2025 14:55:46 -0800 Subject: [PATCH 3/3] errgroup: drop support for Go versions before 1.20 Change-Id: I7de5dfae21c4ffe31d6c16e3df0fed3e2269cb16 Reviewed-on: https://go-review.googlesource.com/c/sync/+/654421 LUCI-TryBot-Result: Go LUCI Reviewed-by: Ian Lance Taylor Auto-Submit: Ian Lance Taylor Commit-Queue: Ian Lance Taylor Reviewed-by: Dmitri Shuralyov Reviewed-by: Dmitri Shuralyov --- errgroup/errgroup.go | 2 +- errgroup/errgroup_test.go | 39 ++++++++++++++++++++++++++++ errgroup/go120.go | 13 ---------- errgroup/go120_test.go | 54 --------------------------------------- errgroup/pre_go120.go | 14 ---------- 5 files changed, 40 insertions(+), 82 deletions(-) delete mode 100644 errgroup/go120.go delete mode 100644 errgroup/go120_test.go delete mode 100644 errgroup/pre_go120.go diff --git a/errgroup/errgroup.go b/errgroup/errgroup.go index b832259..a4ea5d1 100644 --- a/errgroup/errgroup.go +++ b/errgroup/errgroup.go @@ -46,7 +46,7 @@ func (g *Group) done() { // returns a non-nil error or the first time Wait returns, whichever occurs // first. func WithContext(ctx context.Context) (*Group, context.Context) { - ctx, cancel := withCancelCause(ctx) + ctx, cancel := context.WithCancelCause(ctx) return &Group{cancel: cancel}, ctx } diff --git a/errgroup/errgroup_test.go b/errgroup/errgroup_test.go index 0358842..2a491bf 100644 --- a/errgroup/errgroup_test.go +++ b/errgroup/errgroup_test.go @@ -250,6 +250,45 @@ func TestGoLimit(t *testing.T) { } } +func TestCancelCause(t *testing.T) { + errDoom := errors.New("group_test: doomed") + + cases := []struct { + errs []error + want error + }{ + {want: nil}, + {errs: []error{nil}, want: nil}, + {errs: []error{errDoom}, want: errDoom}, + {errs: []error{errDoom, nil}, want: errDoom}, + } + + for _, tc := range cases { + g, ctx := errgroup.WithContext(context.Background()) + + for _, err := range tc.errs { + err := err + g.TryGo(func() error { return err }) + } + + if err := g.Wait(); err != tc.want { + t.Errorf("after %T.TryGo(func() error { return err }) for err in %v\n"+ + "g.Wait() = %v; want %v", + g, tc.errs, err, tc.want) + } + + if tc.want == nil { + tc.want = context.Canceled + } + + if err := context.Cause(ctx); err != tc.want { + t.Errorf("after %T.TryGo(func() error { return err }) for err in %v\n"+ + "context.Cause(ctx) = %v; tc.want %v", + g, tc.errs, err, tc.want) + } + } +} + func BenchmarkGo(b *testing.B) { fn := func() {} g := &errgroup.Group{} diff --git a/errgroup/go120.go b/errgroup/go120.go deleted file mode 100644 index f93c740..0000000 --- a/errgroup/go120.go +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2023 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.20 - -package errgroup - -import "context" - -func withCancelCause(parent context.Context) (context.Context, func(error)) { - return context.WithCancelCause(parent) -} diff --git a/errgroup/go120_test.go b/errgroup/go120_test.go deleted file mode 100644 index 068f104..0000000 --- a/errgroup/go120_test.go +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2023 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.20 - -package errgroup_test - -import ( - "context" - "errors" - "testing" - - "golang.org/x/sync/errgroup" -) - -func TestCancelCause(t *testing.T) { - errDoom := errors.New("group_test: doomed") - - cases := []struct { - errs []error - want error - }{ - {want: nil}, - {errs: []error{nil}, want: nil}, - {errs: []error{errDoom}, want: errDoom}, - {errs: []error{errDoom, nil}, want: errDoom}, - } - - for _, tc := range cases { - g, ctx := errgroup.WithContext(context.Background()) - - for _, err := range tc.errs { - err := err - g.TryGo(func() error { return err }) - } - - if err := g.Wait(); err != tc.want { - t.Errorf("after %T.TryGo(func() error { return err }) for err in %v\n"+ - "g.Wait() = %v; want %v", - g, tc.errs, err, tc.want) - } - - if tc.want == nil { - tc.want = context.Canceled - } - - if err := context.Cause(ctx); err != tc.want { - t.Errorf("after %T.TryGo(func() error { return err }) for err in %v\n"+ - "context.Cause(ctx) = %v; tc.want %v", - g, tc.errs, err, tc.want) - } - } -} diff --git a/errgroup/pre_go120.go b/errgroup/pre_go120.go deleted file mode 100644 index 88ce334..0000000 --- a/errgroup/pre_go120.go +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2023 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !go1.20 - -package errgroup - -import "context" - -func withCancelCause(parent context.Context) (context.Context, func(error)) { - ctx, cancel := context.WithCancel(parent) - return ctx, func(error) { cancel() } -}