@@ -333,43 +333,10 @@ func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) {
333
333
}
334
334
335
335
// If some non-Go code called sigaltstack, adjust.
336
- setStack := false
337
336
var gsignalStack gsignalStack
338
- sp := uintptr (unsafe .Pointer (& sig ))
339
- if sp < g .m .gsignal .stack .lo || sp >= g .m .gsignal .stack .hi {
340
- if sp >= g .m .g0 .stack .lo && sp < g .m .g0 .stack .hi {
341
- // The signal was delivered on the g0 stack.
342
- // This can happen when linked with C code
343
- // using the thread sanitizer, which collects
344
- // signals then delivers them itself by calling
345
- // the signal handler directly when C code,
346
- // including C code called via cgo, calls a
347
- // TSAN-intercepted function such as malloc.
348
- st := stackt {ss_size : g .m .g0 .stack .hi - g .m .g0 .stack .lo }
349
- setSignalstackSP (& st , g .m .g0 .stack .lo )
350
- setGsignalStack (& st , & gsignalStack )
351
- g .m .gsignal .stktopsp = getcallersp ()
352
- setStack = true
353
- } else {
354
- var st stackt
355
- sigaltstack (nil , & st )
356
- if st .ss_flags & _SS_DISABLE != 0 {
357
- setg (nil )
358
- needm (0 )
359
- noSignalStack (sig )
360
- dropm ()
361
- }
362
- stsp := uintptr (unsafe .Pointer (st .ss_sp ))
363
- if sp < stsp || sp >= stsp + st .ss_size {
364
- setg (nil )
365
- needm (0 )
366
- sigNotOnStack (sig )
367
- dropm ()
368
- }
369
- setGsignalStack (& st , & gsignalStack )
370
- g .m .gsignal .stktopsp = getcallersp ()
371
- setStack = true
372
- }
337
+ setStack := adjustSignalStack (sig , g .m , & gsignalStack )
338
+ if setStack {
339
+ g .m .gsignal .stktopsp = getcallersp ()
373
340
}
374
341
375
342
setg (g .m .gsignal )
@@ -386,6 +353,51 @@ func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) {
386
353
}
387
354
}
388
355
356
+ // adjustSignalStack adjusts the current stack guard based on the
357
+ // stack pointer that is actually in use while handling a signal.
358
+ // We do this in case some non-Go code called sigaltstack.
359
+ // This reports whether the stack was adjusted, and if so stores the old
360
+ // signal stack in *gsigstack.
361
+ //go:nosplit
362
+ func adjustSignalStack (sig uint32 , mp * m , gsigStack * gsignalStack ) bool {
363
+ sp := uintptr (unsafe .Pointer (& sig ))
364
+ if sp >= mp .gsignal .stack .lo && sp < mp .gsignal .stack .hi {
365
+ return false
366
+ }
367
+
368
+ if sp >= mp .g0 .stack .lo && sp < mp .g0 .stack .hi {
369
+ // The signal was delivered on the g0 stack.
370
+ // This can happen when linked with C code
371
+ // using the thread sanitizer, which collects
372
+ // signals then delivers them itself by calling
373
+ // the signal handler directly when C code,
374
+ // including C code called via cgo, calls a
375
+ // TSAN-intercepted function such as malloc.
376
+ st := stackt {ss_size : mp .g0 .stack .hi - mp .g0 .stack .lo }
377
+ setSignalstackSP (& st , mp .g0 .stack .lo )
378
+ setGsignalStack (& st , gsigStack )
379
+ return true
380
+ }
381
+
382
+ var st stackt
383
+ sigaltstack (nil , & st )
384
+ if st .ss_flags & _SS_DISABLE != 0 {
385
+ setg (nil )
386
+ needm (0 )
387
+ noSignalStack (sig )
388
+ dropm ()
389
+ }
390
+ stsp := uintptr (unsafe .Pointer (st .ss_sp ))
391
+ if sp < stsp || sp >= stsp + st .ss_size {
392
+ setg (nil )
393
+ needm (0 )
394
+ sigNotOnStack (sig )
395
+ dropm ()
396
+ }
397
+ setGsignalStack (& st , gsigStack )
398
+ return true
399
+ }
400
+
389
401
// crashing is the number of m's we have waited for when implementing
390
402
// GOTRACEBACK=crash when a signal is received.
391
403
var crashing int32
0 commit comments