@@ -274,19 +274,37 @@ func sigpipe() {
274
274
dieFromSignal (_SIGPIPE )
275
275
}
276
276
277
- // sigFetchG fetches the value of G safely when running in a signal handler.
278
277
// On some architectures, the g value may be clobbered when running in a VDSO.
279
278
// See issue #32912.
280
279
//
281
280
//go:nosplit
282
- func sigFetchG (c * sigctxt ) * g {
281
+ func sigClobbered (c * sigctxt ) bool {
283
282
switch GOARCH {
284
283
case "arm" , "arm64" :
285
- if inVDSOPage (c .sigpc ()) {
286
- return nil
287
- }
284
+ return inVDSOPage (c .sigpc ());
285
+ }
286
+ return false
287
+ }
288
+
289
+ // sigpending stores signals during the Go signal handler when the g value is clobbered.
290
+ // See issue #34391.
291
+ var sigpending [(_NSIG + 31 ) / 32 ]uint32
292
+
293
+ func sigAddPending (s uint32 ) {
294
+ p := sigpending [s / 32 ]
295
+ p |= 1 << (s & 31 )
296
+ atomic .Store (& sigpending [s / 32 ], p )
297
+ }
298
+
299
+ // sigClearPending is called from outside the signal handler context.
300
+ // It is called just after the clobbered G value is restored.
301
+ func sigClearPending () {
302
+ for s := 0 ; s < _NSIG ; s ++ {
303
+ p := sigpending [s / 32 ]
304
+ p &^= 1 << (s & 31 )
305
+ atomic .Store (& sigpending [s / 32 ], p )
306
+ raise (uint32 (s ))
288
307
}
289
- return getg ()
290
308
}
291
309
292
310
// sigtrampgo is called from the signal handler function, sigtramp,
@@ -305,7 +323,16 @@ func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) {
305
323
return
306
324
}
307
325
c := & sigctxt {info , ctx }
308
- g := sigFetchG (c )
326
+ if sigClobbered (c ) {
327
+ if sig == _SIGPROF {
328
+ sigprofNonGoPC (c .sigpc ())
329
+ return
330
+ }
331
+ // at this point iscgo must be true
332
+ sigAddPending (sig )
333
+ return
334
+ }
335
+ g := getg ()
309
336
if g == nil {
310
337
if sig == _SIGPROF {
311
338
sigprofNonGoPC (c .sigpc ())
@@ -670,13 +697,19 @@ func sigfwdgo(sig uint32, info *siginfo, ctx unsafe.Pointer) bool {
670
697
if (c .sigcode () == _SI_USER || flags & _SigPanic == 0 ) && sig != _SIGPIPE {
671
698
return false
672
699
}
673
- // Determine if the signal occurred inside Go code. We test that:
674
- // (1) we weren't in VDSO page,
675
- // (2) we were in a goroutine (i.e., m.curg != nil), and
676
- // (3) we weren't in CGO.
677
- g := sigFetchG (c )
678
- if g != nil && g .m != nil && g .m .curg != nil && ! g .m .incgo {
679
- return false
700
+ if sigClobbered (c ) {
701
+ // There is no handler to be forwarded to.
702
+ if ! iscgo {
703
+ return false
704
+ }
705
+ } else {
706
+ // Determine if the signal occurred inside Go code. We test that:
707
+ // (1) we were in a goroutine (i.e., m.curg != nil), and
708
+ // (2) we weren't in CGO.
709
+ g := getg ()
710
+ if g != nil && g .m != nil && g .m .curg != nil && ! g .m .incgo {
711
+ return false
712
+ }
680
713
}
681
714
682
715
// Signal not handled by Go, forward it.
0 commit comments