-
Notifications
You must be signed in to change notification settings - Fork 17.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
cmd/go: add a GODEBUG to limit the number of concurrent network conne…
…ctions I implemented this in order to debug connection failures on a new-to-me VM development environment that uses Cloud NAT. It doesn't directly fix the bug, but perhaps folks will find it useful to diagnose port-exhaustion-related flakiness in other environments. For #52545. Change-Id: Icd3f13dcf62e718560c4f4a965a4df7c1bd785ce Reviewed-on: https://go-review.googlesource.com/c/go/+/473277 Run-TryBot: Bryan Mills <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Michael Matloob <[email protected]> Auto-Submit: Bryan Mills <[email protected]>
- Loading branch information
Showing
9 changed files
with
284 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
// 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. | ||
|
||
package base | ||
|
||
import ( | ||
"fmt" | ||
"internal/godebug" | ||
"runtime" | ||
"strconv" | ||
"sync" | ||
) | ||
|
||
var NetLimitGodebug = godebug.New("#cmdgonetlimit") | ||
|
||
// NetLimit returns the limit on concurrent network operations | ||
// configured by GODEBUG=cmdgonetlimit, if any. | ||
// | ||
// A limit of 0 (indicated by 0, true) means that network operations should not | ||
// be allowed. | ||
func NetLimit() (int, bool) { | ||
netLimitOnce.Do(func() { | ||
s := NetLimitGodebug.Value() | ||
if s == "" { | ||
return | ||
} | ||
|
||
n, err := strconv.Atoi(s) | ||
if err != nil { | ||
Fatalf("invalid %s: %v", NetLimitGodebug.Name(), err) | ||
} | ||
if n < 0 { | ||
// Treat negative values as unlimited. | ||
return | ||
} | ||
netLimitSem = make(chan struct{}, n) | ||
}) | ||
|
||
return cap(netLimitSem), netLimitSem != nil | ||
} | ||
|
||
// AcquireNet acquires a semaphore token for a network operation. | ||
func AcquireNet() (release func(), err error) { | ||
hasToken := false | ||
if n, ok := NetLimit(); ok { | ||
if n == 0 { | ||
return nil, fmt.Errorf("network disabled by %v=%v", NetLimitGodebug.Name(), NetLimitGodebug.Value()) | ||
} | ||
netLimitSem <- struct{}{} | ||
hasToken = true | ||
} | ||
|
||
checker := new(netTokenChecker) | ||
runtime.SetFinalizer(checker, (*netTokenChecker).panicUnreleased) | ||
|
||
return func() { | ||
if checker.released { | ||
panic("internal error: net token released twice") | ||
} | ||
checker.released = true | ||
if hasToken { | ||
<-netLimitSem | ||
} | ||
runtime.SetFinalizer(checker, nil) | ||
}, nil | ||
} | ||
|
||
var ( | ||
netLimitOnce sync.Once | ||
netLimitSem chan struct{} | ||
) | ||
|
||
type netTokenChecker struct { | ||
released bool | ||
// We want to use a finalizer to check that all acquired tokens are returned, | ||
// so we arbitrarily pad the tokens with a string to defeat the runtime's | ||
// “tiny allocator”. | ||
unusedAvoidTinyAllocator string | ||
} | ||
|
||
func (c *netTokenChecker) panicUnreleased() { | ||
panic("internal error: net token acquired but not released") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.