semaphore: panic on negative capacity NewWeighted currently accepts a negative capacity, creating a semaphore for which even a zero-weight acquisition cannot succeed. Reject negative capacities at construction time while continuing to allow zero capacity. Updates golang/go#80183 Change-Id: Id819efed370bb81e8bf13891d781f90e298a2a07 Reviewed-on: https://go-review.googlesource.com/c/sync/+/808920 Auto-Submit: Alan Donovan <adonovan@google.com> Reviewed-by: race quite <quiterace@gmail.com> LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Alan Donovan <adonovan@google.com> Reviewed-by: David Chase <drchase@google.com>
diff --git a/semaphore/semaphore.go b/semaphore/semaphore.go index 96a035a..f2a7d3f 100644 --- a/semaphore/semaphore.go +++ b/semaphore/semaphore.go
@@ -17,10 +17,13 @@ } // NewWeighted creates a new weighted semaphore with the given -// maximum combined weight for concurrent access. +// maximum combined weight for concurrent access. NewWeighted panics if n is +// negative. func NewWeighted(n int64) *Weighted { - w := &Weighted{size: n} - return w + if n < 0 { + panic("semaphore: size < 0") + } + return &Weighted{size: n} } // Weighted provides a way to bound concurrent access to a resource.
diff --git a/semaphore/semaphore_test.go b/semaphore/semaphore_test.go index 1a2eb7a..058a382 100644 --- a/semaphore/semaphore_test.go +++ b/semaphore/semaphore_test.go
@@ -56,12 +56,32 @@ w.Release(1) } +func TestWeightedNegativeSizePanic(t *testing.T) { + t.Parallel() + + defer func() { + if recover() == nil { + t.Fatal("NewWeighted with negative size did not panic") + } + }() + semaphore.NewWeighted(-1) +} + +func TestWeightedZeroSize(t *testing.T) { + t.Parallel() + + w := semaphore.NewWeighted(0) + if !w.TryAcquire(0) { + t.Fatal("TryAcquire on a zero-sized semaphore with zero weight failed") + } +} + func TestWeightedNegativeWeightPanic(t *testing.T) { t.Parallel() ctx := context.Background() w := semaphore.NewWeighted(1) - + func() { defer func() { if recover() == nil {