File tree Expand file tree Collapse file tree 2 files changed +53
-1
lines changed Expand file tree Collapse file tree 2 files changed +53
-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,42 @@ func TestWaitGroupGo(t *testing.T) {
110115 }
111116}
112117
118+ // We define our own main function so that portions of
119+ // some tests can run in a separate (child) process.
120+ func TestMain (m * testing.M ) {
121+ switch os .Getenv ("ENTRYPOINT" ) {
122+ case "child" :
123+ child ()
124+ default :
125+ os .Exit (m .Run ())
126+ }
127+ }
128+ func TestIssue76126 (t * testing.T ) {
129+ // Call child in a child process
130+ // and inspect its failure message.
131+ cmd := exec .Command (os .Args [0 ], os .Args [1 :]... )
132+ cmd .Env = append (os .Environ (),
133+ "ENTRYPOINT=child" )
134+ buf := new (bytes.Buffer )
135+ cmd .Stdout = buf
136+ cmd .Stderr = buf
137+ cmd .Run () // ignore error
138+ got := buf .String ()
139+ if strings .Contains (got , "panic: test" ) {
140+ // ok
141+ } else {
142+ t .Errorf ("got: %s" , buf )
143+ }
144+ }
145+ func child () {
146+ var wg sync.WaitGroup
147+ wg .Go (func () {
148+ panic ("test" )
149+ })
150+ wg .Wait () // process should terminate here
151+ panic ("Wait returned" ) // must not be reached
152+ }
153+
113154func BenchmarkWaitGroupUncontended (b * testing.B ) {
114155 type PaddedWaitGroup struct {
115156 WaitGroup
You can’t perform that action at this time.
0 commit comments