File tree Expand file tree Collapse file tree 2 files changed +56
-1
lines changed Expand file tree Collapse file tree 2 files changed +56
-1
lines changed Original file line number Diff line number Diff line change @@ -236,7 +236,18 @@ func (wg *WaitGroup) Wait() {
236236func (wg * WaitGroup ) Go (f func ()) {
237237 wg .Add (1 )
238238 go func () {
239- defer wg .Done ()
239+ defer func () {
240+ if x := recover (); x != nil {
241+ // Don't call Done as it may cause Wait to unblock,
242+ // so that the main goroutine races with the runtime.fatal
243+ // resulting from unhandled panic.
244+ panic (x )
245+ }
246+
247+ // f completed normally, or abruptly using goexit.
248+ // Either way, decrement the semaphore.
249+ wg .Done ()
250+ }()
240251 f ()
241252 }()
242253}
Original file line number Diff line number Diff line change 55package sync_test
66
77import (
8+ "bytes"
9+ "os"
10+ "os/exec"
11+ "runtime"
12+ "strings"
13+ "sync"
814 . "sync"
915 "sync/atomic"
1016 "testing"
@@ -110,6 +116,44 @@ func TestWaitGroupGo(t *testing.T) {
110116 }
111117}
112118
119+ func TestIssue76126 (t * testing.T ) {
120+ if runtime .GOOS == "js" || runtime .GOOS == "wasip1" {
121+ t .Skip ("skipping test on js/wasip1" )
122+ }
123+ // Call child in a child process
124+ // and inspect its failure message.
125+ cmd := exec .Command (os .Args [0 ],
126+ append (os .Args [1 :], "-test.run" , "^TestIssue76126Child$/^child$" )... )
127+ cmd .Env = append (os .Environ (),
128+ "ENTRYPOINT=child" )
129+ buf := new (bytes.Buffer )
130+ cmd .Stderr = buf
131+ cmd .Run () // ignore error
132+
133+ got := buf .String ()
134+ if strings .Contains (got , "panic: test" ) {
135+ // ok
136+ } else {
137+ t .Errorf ("missing panic: test\n %s" , got )
138+ }
139+ }
140+
141+ func TestIssue76126Child (t * testing.T ) {
142+ t .Run ("child" , func (t * testing.T ) {
143+ switch os .Getenv ("ENTRYPOINT" ) {
144+ case "child" :
145+ default :
146+ t .Skip ("not child" )
147+ }
148+ var wg sync.WaitGroup
149+ wg .Go (func () {
150+ panic ("test" )
151+ })
152+ wg .Wait () // process should terminate here
153+ panic ("Wait returned" ) // must not be reached
154+ })
155+ }
156+
113157func BenchmarkWaitGroupUncontended (b * testing.B ) {
114158 type PaddedWaitGroup struct {
115159 WaitGroup
You can’t perform that action at this time.
0 commit comments