File tree Expand file tree Collapse file tree 2 files changed +52
-1
lines changed Expand file tree Collapse file tree 2 files changed +52
-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+ "strings"
12+ "sync"
813 . "sync"
914 "sync/atomic"
1015 "testing"
@@ -110,6 +115,41 @@ func TestWaitGroupGo(t *testing.T) {
110115 }
111116}
112117
118+ func TestIssue76126 (t * testing.T ) {
119+ // Call child in a child process
120+ // and inspect its failure message.
121+ cmd := exec .Command (os .Args [0 ],
122+ append (os .Args [1 :], "-test.run" , "^TestIssue76126Child$/^child$" )... )
123+ cmd .Env = append (os .Environ (),
124+ "ENTRYPOINT=child" )
125+ buf := new (bytes.Buffer )
126+ cmd .Stderr = buf
127+ cmd .Run () // ignore error
128+
129+ got := buf .String ()
130+ if strings .Contains (got , "panic: test" ) {
131+ // ok
132+ } else {
133+ t .Errorf ("missing panic: test\n %s" , got )
134+ }
135+ }
136+
137+ func TestIssue76126Child (t * testing.T ) {
138+ t .Run ("child" , func (t * testing.T ) {
139+ switch os .Getenv ("ENTRYPOINT" ) {
140+ case "child" :
141+ default :
142+ t .Skip ("not child" )
143+ }
144+ var wg sync.WaitGroup
145+ wg .Go (func () {
146+ panic ("test" )
147+ })
148+ wg .Wait () // process should terminate here
149+ panic ("Wait returned" ) // must not be reached
150+ })
151+ }
152+
113153func BenchmarkWaitGroupUncontended (b * testing.B ) {
114154 type PaddedWaitGroup struct {
115155 WaitGroup
You can’t perform that action at this time.
0 commit comments