@@ -597,7 +597,7 @@ func adjustSignalStack(sig uint32, mp *m, gsigStack *gsignalStack) bool {
597
597
598
598
// crashing is the number of m's we have waited for when implementing
599
599
// GOTRACEBACK=crash when a signal is received.
600
- var crashing int32
600
+ var crashing atomic. Int32
601
601
602
602
// testSigtrap and testSigusr1 are used by the runtime tests. If
603
603
// non-nil, it is called on SIGTRAP/SIGUSR1. If it returns true, the
@@ -730,7 +730,7 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
730
730
mp .throwing = throwTypeRuntime
731
731
mp .caughtsig .set (gp )
732
732
733
- if crashing == 0 {
733
+ if crashing . Load () == 0 {
734
734
startpanic_m ()
735
735
}
736
736
@@ -740,11 +740,11 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
740
740
if level > 0 {
741
741
goroutineheader (gp )
742
742
tracebacktrap (c .sigpc (), c .sigsp (), c .siglr (), gp )
743
- if crashing > 0 && gp != mp .curg && mp .curg != nil && readgstatus (mp .curg )&^_Gscan == _Grunning {
743
+ if crashing . Load () > 0 && gp != mp .curg && mp .curg != nil && readgstatus (mp .curg )&^_Gscan == _Grunning {
744
744
// tracebackothers on original m skipped this one; trace it now.
745
745
goroutineheader (mp .curg )
746
746
traceback (^ uintptr (0 ), ^ uintptr (0 ), 0 , mp .curg )
747
- } else if crashing == 0 {
747
+ } else if crashing . Load () == 0 {
748
748
tracebackothers (gp )
749
749
print ("\n " )
750
750
}
@@ -753,29 +753,29 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
753
753
754
754
if docrash {
755
755
isCrashThread := false
756
- if crashing == 0 {
756
+ if crashing . Load () == 0 {
757
757
isCrashThread = true
758
758
}
759
- crashing ++
760
- if crashing < mcount ()- int32 (extraMLength .Load ()) {
759
+ crashing . Add ( 1 )
760
+ if crashing . Load () < mcount ()- int32 (extraMLength .Load ()) {
761
761
// There are other m's that need to dump their stacks.
762
762
// Relay SIGQUIT to the next m by sending it to the current process.
763
763
// All m's that have already received SIGQUIT have signal masks blocking
764
764
// receipt of any signals, so the SIGQUIT will go to an m that hasn't seen it yet.
765
765
// The first m will wait until all ms received the SIGQUIT, then crash/exit.
766
766
// Just in case the relaying gets botched, each m involved in
767
767
// the relay sleeps for 5 seconds and then does the crash/exit itself.
768
- // In expected operation, the first m will wait until the last m has received the SIGQUIT,
768
+ // The faulting m is crashing first so it is the faulting thread in the core dump (see issue #63277):
769
+ // in expected operation, the first m will wait until the last m has received the SIGQUIT,
769
770
// and then run crash/exit and the process is gone.
770
771
// However, if it spends more than 5 seconds to send SIGQUIT to all ms,
771
772
// any of ms may crash/exit the process after waiting for 5 seconds.
772
773
print ("\n -----\n \n " )
773
774
raiseproc (_SIGQUIT )
774
775
}
775
- // fix #63277
776
776
if isCrashThread {
777
777
i := 0
778
- for (crashing < mcount ()- int32 (extraMLength .Load ()) && i < 10 ) {
778
+ for (crashing . Load () < mcount ()- int32 (extraMLength .Load ())) && i < 10 {
779
779
i ++
780
780
usleep (500 * 1000 )
781
781
}
0 commit comments