Source file src/pkg/runtime/panic.go
1
2
3
4
5 package runtime
6
7 import (
8 "runtime/internal/atomic"
9 "runtime/internal/sys"
10 "unsafe"
11 )
12
13
14
15
16
17
18 func panicCheck1(pc uintptr, msg string) {
19 if sys.GoarchWasm == 0 && hasPrefix(funcname(findfunc(pc)), "runtime.") {
20
21 throw(msg)
22 }
23
24
25 gp := getg()
26 if gp != nil && gp.m != nil && gp.m.mallocing != 0 {
27 throw(msg)
28 }
29 }
30
31
32
33
34
35
36 func panicCheck2(err string) {
37
38
39 gp := getg()
40 if gp != nil && gp.m != nil && gp.m.mallocing != 0 {
41 throw(err)
42 }
43 }
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73 func goPanicIndex(x int, y int) {
74 panicCheck1(getcallerpc(), "index out of range")
75 panic(boundsError{x: int64(x), signed: true, y: y, code: boundsIndex})
76 }
77 func goPanicIndexU(x uint, y int) {
78 panicCheck1(getcallerpc(), "index out of range")
79 panic(boundsError{x: int64(x), signed: false, y: y, code: boundsIndex})
80 }
81
82
83 func goPanicSliceAlen(x int, y int) {
84 panicCheck1(getcallerpc(), "slice bounds out of range")
85 panic(boundsError{x: int64(x), signed: true, y: y, code: boundsSliceAlen})
86 }
87 func goPanicSliceAlenU(x uint, y int) {
88 panicCheck1(getcallerpc(), "slice bounds out of range")
89 panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSliceAlen})
90 }
91 func goPanicSliceAcap(x int, y int) {
92 panicCheck1(getcallerpc(), "slice bounds out of range")
93 panic(boundsError{x: int64(x), signed: true, y: y, code: boundsSliceAcap})
94 }
95 func goPanicSliceAcapU(x uint, y int) {
96 panicCheck1(getcallerpc(), "slice bounds out of range")
97 panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSliceAcap})
98 }
99
100
101 func goPanicSliceB(x int, y int) {
102 panicCheck1(getcallerpc(), "slice bounds out of range")
103 panic(boundsError{x: int64(x), signed: true, y: y, code: boundsSliceB})
104 }
105 func goPanicSliceBU(x uint, y int) {
106 panicCheck1(getcallerpc(), "slice bounds out of range")
107 panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSliceB})
108 }
109
110
111 func goPanicSlice3Alen(x int, y int) {
112 panicCheck1(getcallerpc(), "slice bounds out of range")
113 panic(boundsError{x: int64(x), signed: true, y: y, code: boundsSlice3Alen})
114 }
115 func goPanicSlice3AlenU(x uint, y int) {
116 panicCheck1(getcallerpc(), "slice bounds out of range")
117 panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSlice3Alen})
118 }
119 func goPanicSlice3Acap(x int, y int) {
120 panicCheck1(getcallerpc(), "slice bounds out of range")
121 panic(boundsError{x: int64(x), signed: true, y: y, code: boundsSlice3Acap})
122 }
123 func goPanicSlice3AcapU(x uint, y int) {
124 panicCheck1(getcallerpc(), "slice bounds out of range")
125 panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSlice3Acap})
126 }
127
128
129 func goPanicSlice3B(x int, y int) {
130 panicCheck1(getcallerpc(), "slice bounds out of range")
131 panic(boundsError{x: int64(x), signed: true, y: y, code: boundsSlice3B})
132 }
133 func goPanicSlice3BU(x uint, y int) {
134 panicCheck1(getcallerpc(), "slice bounds out of range")
135 panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSlice3B})
136 }
137
138
139 func goPanicSlice3C(x int, y int) {
140 panicCheck1(getcallerpc(), "slice bounds out of range")
141 panic(boundsError{x: int64(x), signed: true, y: y, code: boundsSlice3C})
142 }
143 func goPanicSlice3CU(x uint, y int) {
144 panicCheck1(getcallerpc(), "slice bounds out of range")
145 panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSlice3C})
146 }
147
148
149
150 func panicIndex(x int, y int)
151 func panicIndexU(x uint, y int)
152 func panicSliceAlen(x int, y int)
153 func panicSliceAlenU(x uint, y int)
154 func panicSliceAcap(x int, y int)
155 func panicSliceAcapU(x uint, y int)
156 func panicSliceB(x int, y int)
157 func panicSliceBU(x uint, y int)
158 func panicSlice3Alen(x int, y int)
159 func panicSlice3AlenU(x uint, y int)
160 func panicSlice3Acap(x int, y int)
161 func panicSlice3AcapU(x uint, y int)
162 func panicSlice3B(x int, y int)
163 func panicSlice3BU(x uint, y int)
164 func panicSlice3C(x int, y int)
165 func panicSlice3CU(x uint, y int)
166
167 var shiftError = error(errorString("negative shift amount"))
168
169 func panicshift() {
170 panicCheck1(getcallerpc(), "negative shift amount")
171 panic(shiftError)
172 }
173
174 var divideError = error(errorString("integer divide by zero"))
175
176 func panicdivide() {
177 panicCheck2("integer divide by zero")
178 panic(divideError)
179 }
180
181 var overflowError = error(errorString("integer overflow"))
182
183 func panicoverflow() {
184 panicCheck2("integer overflow")
185 panic(overflowError)
186 }
187
188 var floatError = error(errorString("floating point error"))
189
190 func panicfloat() {
191 panicCheck2("floating point error")
192 panic(floatError)
193 }
194
195 var memoryError = error(errorString("invalid memory address or nil pointer dereference"))
196
197 func panicmem() {
198 panicCheck2("invalid memory address or nil pointer dereference")
199 panic(memoryError)
200 }
201
202
203
204
205 func deferproc(siz int32, fn *funcval) {
206 if getg().m.curg != getg() {
207
208 throw("defer on system stack")
209 }
210
211
212
213
214
215
216 sp := getcallersp()
217 argp := uintptr(unsafe.Pointer(&fn)) + unsafe.Sizeof(fn)
218 callerpc := getcallerpc()
219
220 d := newdefer(siz)
221 if d._panic != nil {
222 throw("deferproc: d.panic != nil after newdefer")
223 }
224 d.fn = fn
225 d.pc = callerpc
226 d.sp = sp
227 switch siz {
228 case 0:
229
230 case sys.PtrSize:
231 *(*uintptr)(deferArgs(d)) = *(*uintptr)(unsafe.Pointer(argp))
232 default:
233 memmove(deferArgs(d), unsafe.Pointer(argp), uintptr(siz))
234 }
235
236
237
238
239
240
241
242 return0()
243
244
245 }
246
247
248
249
250
251
252
253
254
255 func deferprocStack(d *_defer) {
256 gp := getg()
257 if gp.m.curg != gp {
258
259 throw("defer on system stack")
260 }
261
262
263
264 d.started = false
265 d.heap = false
266 d.sp = getcallersp()
267 d.pc = getcallerpc()
268
269
270
271
272
273
274
275
276
277
278 *(*uintptr)(unsafe.Pointer(&d._panic)) = 0
279 *(*uintptr)(unsafe.Pointer(&d.link)) = uintptr(unsafe.Pointer(gp._defer))
280 *(*uintptr)(unsafe.Pointer(&gp._defer)) = uintptr(unsafe.Pointer(d))
281
282 return0()
283
284
285 }
286
287
288
289
290
291 const (
292 deferHeaderSize = unsafe.Sizeof(_defer{})
293 minDeferAlloc = (deferHeaderSize + 15) &^ 15
294 minDeferArgs = minDeferAlloc - deferHeaderSize
295 )
296
297
298
299 func deferclass(siz uintptr) uintptr {
300 if siz <= minDeferArgs {
301 return 0
302 }
303 return (siz - minDeferArgs + 15) / 16
304 }
305
306
307 func totaldefersize(siz uintptr) uintptr {
308 if siz <= minDeferArgs {
309 return minDeferAlloc
310 }
311 return deferHeaderSize + siz
312 }
313
314
315
316 func testdefersizes() {
317 var m [len(p{}.deferpool)]int32
318
319 for i := range m {
320 m[i] = -1
321 }
322 for i := uintptr(0); ; i++ {
323 defersc := deferclass(i)
324 if defersc >= uintptr(len(m)) {
325 break
326 }
327 siz := roundupsize(totaldefersize(i))
328 if m[defersc] < 0 {
329 m[defersc] = int32(siz)
330 continue
331 }
332 if m[defersc] != int32(siz) {
333 print("bad defer size class: i=", i, " siz=", siz, " defersc=", defersc, "\n")
334 throw("bad defer size class")
335 }
336 }
337 }
338
339
340
341
342 func deferArgs(d *_defer) unsafe.Pointer {
343 if d.siz == 0 {
344
345 return nil
346 }
347 return add(unsafe.Pointer(d), unsafe.Sizeof(*d))
348 }
349
350 var deferType *_type
351
352 func init() {
353 var x interface{}
354 x = (*_defer)(nil)
355 deferType = (*(**ptrtype)(unsafe.Pointer(&x))).elem
356 }
357
358
359
360
361
362
363
364
365 func newdefer(siz int32) *_defer {
366 var d *_defer
367 sc := deferclass(uintptr(siz))
368 gp := getg()
369 if sc < uintptr(len(p{}.deferpool)) {
370 pp := gp.m.p.ptr()
371 if len(pp.deferpool[sc]) == 0 && sched.deferpool[sc] != nil {
372
373
374 systemstack(func() {
375 lock(&sched.deferlock)
376 for len(pp.deferpool[sc]) < cap(pp.deferpool[sc])/2 && sched.deferpool[sc] != nil {
377 d := sched.deferpool[sc]
378 sched.deferpool[sc] = d.link
379 d.link = nil
380 pp.deferpool[sc] = append(pp.deferpool[sc], d)
381 }
382 unlock(&sched.deferlock)
383 })
384 }
385 if n := len(pp.deferpool[sc]); n > 0 {
386 d = pp.deferpool[sc][n-1]
387 pp.deferpool[sc][n-1] = nil
388 pp.deferpool[sc] = pp.deferpool[sc][:n-1]
389 }
390 }
391 if d == nil {
392
393 systemstack(func() {
394 total := roundupsize(totaldefersize(uintptr(siz)))
395 d = (*_defer)(mallocgc(total, deferType, true))
396 })
397 if debugCachedWork {
398
399
400
401 d.siz = siz
402 d.link = gp._defer
403 gp._defer = d
404 return d
405 }
406 }
407 d.siz = siz
408 d.heap = true
409 d.link = gp._defer
410 gp._defer = d
411 return d
412 }
413
414
415
416
417
418
419
420
421 func freedefer(d *_defer) {
422 if d._panic != nil {
423 freedeferpanic()
424 }
425 if d.fn != nil {
426 freedeferfn()
427 }
428 if !d.heap {
429 return
430 }
431 sc := deferclass(uintptr(d.siz))
432 if sc >= uintptr(len(p{}.deferpool)) {
433 return
434 }
435 pp := getg().m.p.ptr()
436 if len(pp.deferpool[sc]) == cap(pp.deferpool[sc]) {
437
438
439
440
441 systemstack(func() {
442 var first, last *_defer
443 for len(pp.deferpool[sc]) > cap(pp.deferpool[sc])/2 {
444 n := len(pp.deferpool[sc])
445 d := pp.deferpool[sc][n-1]
446 pp.deferpool[sc][n-1] = nil
447 pp.deferpool[sc] = pp.deferpool[sc][:n-1]
448 if first == nil {
449 first = d
450 } else {
451 last.link = d
452 }
453 last = d
454 }
455 lock(&sched.deferlock)
456 last.link = sched.deferpool[sc]
457 sched.deferpool[sc] = first
458 unlock(&sched.deferlock)
459 })
460 }
461
462
463
464 d.siz = 0
465 d.started = false
466 d.sp = 0
467 d.pc = 0
468
469
470
471 d.link = nil
472
473 pp.deferpool[sc] = append(pp.deferpool[sc], d)
474 }
475
476
477
478 func freedeferpanic() {
479
480 throw("freedefer with d._panic != nil")
481 }
482
483 func freedeferfn() {
484
485 throw("freedefer with d.fn != nil")
486 }
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502 func deferreturn(arg0 uintptr) {
503 gp := getg()
504 d := gp._defer
505 if d == nil {
506 return
507 }
508 sp := getcallersp()
509 if d.sp != sp {
510 return
511 }
512
513
514
515
516
517
518
519 switch d.siz {
520 case 0:
521
522 case sys.PtrSize:
523 *(*uintptr)(unsafe.Pointer(&arg0)) = *(*uintptr)(deferArgs(d))
524 default:
525 memmove(unsafe.Pointer(&arg0), deferArgs(d), uintptr(d.siz))
526 }
527 fn := d.fn
528 d.fn = nil
529 gp._defer = d.link
530 freedefer(d)
531 jmpdefer(fn, uintptr(unsafe.Pointer(&arg0)))
532 }
533
534
535
536
537
538
539
540
541
542 func Goexit() {
543
544
545
546 gp := getg()
547 for {
548 d := gp._defer
549 if d == nil {
550 break
551 }
552 if d.started {
553 if d._panic != nil {
554 d._panic.aborted = true
555 d._panic = nil
556 }
557 d.fn = nil
558 gp._defer = d.link
559 freedefer(d)
560 continue
561 }
562 d.started = true
563 reflectcall(nil, unsafe.Pointer(d.fn), deferArgs(d), uint32(d.siz), uint32(d.siz))
564 if gp._defer != d {
565 throw("bad defer entry in Goexit")
566 }
567 d._panic = nil
568 d.fn = nil
569 gp._defer = d.link
570 freedefer(d)
571
572 }
573 goexit1()
574 }
575
576
577
578 func preprintpanics(p *_panic) {
579 defer func() {
580 if recover() != nil {
581 throw("panic while printing panic value")
582 }
583 }()
584 for p != nil {
585 switch v := p.arg.(type) {
586 case error:
587 p.arg = v.Error()
588 case stringer:
589 p.arg = v.String()
590 }
591 p = p.link
592 }
593 }
594
595
596
597 func printpanics(p *_panic) {
598 if p.link != nil {
599 printpanics(p.link)
600 print("\t")
601 }
602 print("panic: ")
603 printany(p.arg)
604 if p.recovered {
605 print(" [recovered]")
606 }
607 print("\n")
608 }
609
610
611 func gopanic(e interface{}) {
612 gp := getg()
613 if gp.m.curg != gp {
614 print("panic: ")
615 printany(e)
616 print("\n")
617 throw("panic on system stack")
618 }
619
620 if gp.m.mallocing != 0 {
621 print("panic: ")
622 printany(e)
623 print("\n")
624 throw("panic during malloc")
625 }
626 if gp.m.preemptoff != "" {
627 print("panic: ")
628 printany(e)
629 print("\n")
630 print("preempt off reason: ")
631 print(gp.m.preemptoff)
632 print("\n")
633 throw("panic during preemptoff")
634 }
635 if gp.m.locks != 0 {
636 print("panic: ")
637 printany(e)
638 print("\n")
639 throw("panic holding locks")
640 }
641
642 var p _panic
643 p.arg = e
644 p.link = gp._panic
645 gp._panic = (*_panic)(noescape(unsafe.Pointer(&p)))
646
647 atomic.Xadd(&runningPanicDefers, 1)
648
649 for {
650 d := gp._defer
651 if d == nil {
652 break
653 }
654
655
656
657 if d.started {
658 if d._panic != nil {
659 d._panic.aborted = true
660 }
661 d._panic = nil
662 d.fn = nil
663 gp._defer = d.link
664 freedefer(d)
665 continue
666 }
667
668
669
670
671 d.started = true
672
673
674
675
676 d._panic = (*_panic)(noescape(unsafe.Pointer(&p)))
677
678 p.argp = unsafe.Pointer(getargp(0))
679 reflectcall(nil, unsafe.Pointer(d.fn), deferArgs(d), uint32(d.siz), uint32(d.siz))
680 p.argp = nil
681
682
683 if gp._defer != d {
684 throw("bad defer entry in panic")
685 }
686 d._panic = nil
687 d.fn = nil
688 gp._defer = d.link
689
690
691
692
693 pc := d.pc
694 sp := unsafe.Pointer(d.sp)
695 freedefer(d)
696 if p.recovered {
697 atomic.Xadd(&runningPanicDefers, -1)
698
699 gp._panic = p.link
700
701
702 for gp._panic != nil && gp._panic.aborted {
703 gp._panic = gp._panic.link
704 }
705 if gp._panic == nil {
706 gp.sig = 0
707 }
708
709 gp.sigcode0 = uintptr(sp)
710 gp.sigcode1 = pc
711 mcall(recovery)
712 throw("recovery failed")
713 }
714 }
715
716
717
718
719
720 preprintpanics(gp._panic)
721
722 fatalpanic(gp._panic)
723 *(*int)(nil) = 0
724 }
725
726
727
728
729
730 func getargp(x int) uintptr {
731
732 return uintptr(noescape(unsafe.Pointer(&x)))
733 }
734
735
736
737
738
739
740
741
742 func gorecover(argp uintptr) interface{} {
743
744
745
746
747
748
749 gp := getg()
750 p := gp._panic
751 if p != nil && !p.recovered && argp == uintptr(p.argp) {
752 p.recovered = true
753 return p.arg
754 }
755 return nil
756 }
757
758
759 func sync_throw(s string) {
760 throw(s)
761 }
762
763
764 func throw(s string) {
765
766
767 systemstack(func() {
768 print("fatal error: ", s, "\n")
769 })
770 gp := getg()
771 if gp.m.throwing == 0 {
772 gp.m.throwing = 1
773 }
774 fatalthrow()
775 *(*int)(nil) = 0
776 }
777
778
779
780
781 var runningPanicDefers uint32
782
783
784
785 var panicking uint32
786
787
788
789 var paniclk mutex
790
791
792
793
794 func recovery(gp *g) {
795
796 sp := gp.sigcode0
797 pc := gp.sigcode1
798
799
800 if sp != 0 && (sp < gp.stack.lo || gp.stack.hi < sp) {
801 print("recover: ", hex(sp), " not in [", hex(gp.stack.lo), ", ", hex(gp.stack.hi), "]\n")
802 throw("bad recovery")
803 }
804
805
806
807
808 gp.sched.sp = sp
809 gp.sched.pc = pc
810 gp.sched.lr = 0
811 gp.sched.ret = 1
812 gogo(&gp.sched)
813 }
814
815
816
817
818
819
820 func fatalthrow() {
821 pc := getcallerpc()
822 sp := getcallersp()
823 gp := getg()
824
825
826 systemstack(func() {
827 startpanic_m()
828
829 if dopanic_m(gp, pc, sp) {
830
831
832
833 crash()
834 }
835
836 exit(2)
837 })
838
839 *(*int)(nil) = 0
840 }
841
842
843
844
845
846
847 func fatalpanic(msgs *_panic) {
848 pc := getcallerpc()
849 sp := getcallersp()
850 gp := getg()
851 var docrash bool
852
853
854 systemstack(func() {
855 if startpanic_m() && msgs != nil {
856
857
858
859
860
861
862 atomic.Xadd(&runningPanicDefers, -1)
863
864 printpanics(msgs)
865 }
866
867 docrash = dopanic_m(gp, pc, sp)
868 })
869
870 if docrash {
871
872
873
874 crash()
875 }
876
877 systemstack(func() {
878 exit(2)
879 })
880
881 *(*int)(nil) = 0
882 }
883
884
885
886
887
888
889
890
891
892
893
894
895
896 func startpanic_m() bool {
897 _g_ := getg()
898 if mheap_.cachealloc.size == 0 {
899 print("runtime: panic before malloc heap initialized\n")
900 }
901
902
903
904
905 _g_.m.mallocing++
906
907
908
909 if _g_.m.locks < 0 {
910 _g_.m.locks = 1
911 }
912
913 switch _g_.m.dying {
914 case 0:
915
916 _g_.m.dying = 1
917 atomic.Xadd(&panicking, 1)
918 lock(&paniclk)
919 if debug.schedtrace > 0 || debug.scheddetail > 0 {
920 schedtrace(true)
921 }
922 freezetheworld()
923 return true
924 case 1:
925
926
927 _g_.m.dying = 2
928 print("panic during panic\n")
929 return false
930 case 2:
931
932
933 _g_.m.dying = 3
934 print("stack trace unavailable\n")
935 exit(4)
936 fallthrough
937 default:
938
939 exit(5)
940 return false
941 }
942 }
943
944 var didothers bool
945 var deadlock mutex
946
947 func dopanic_m(gp *g, pc, sp uintptr) bool {
948 if gp.sig != 0 {
949 signame := signame(gp.sig)
950 if signame != "" {
951 print("[signal ", signame)
952 } else {
953 print("[signal ", hex(gp.sig))
954 }
955 print(" code=", hex(gp.sigcode0), " addr=", hex(gp.sigcode1), " pc=", hex(gp.sigpc), "]\n")
956 }
957
958 level, all, docrash := gotraceback()
959 _g_ := getg()
960 if level > 0 {
961 if gp != gp.m.curg {
962 all = true
963 }
964 if gp != gp.m.g0 {
965 print("\n")
966 goroutineheader(gp)
967 traceback(pc, sp, 0, gp)
968 } else if level >= 2 || _g_.m.throwing > 0 {
969 print("\nruntime stack:\n")
970 traceback(pc, sp, 0, gp)
971 }
972 if !didothers && all {
973 didothers = true
974 tracebackothers(gp)
975 }
976 }
977 unlock(&paniclk)
978
979 if atomic.Xadd(&panicking, -1) != 0 {
980
981
982
983
984 lock(&deadlock)
985 lock(&deadlock)
986 }
987
988 printDebugLog()
989
990 return docrash
991 }
992
993
994
995
996
997 func canpanic(gp *g) bool {
998
999
1000
1001 _g_ := getg()
1002 _m_ := _g_.m
1003
1004
1005
1006
1007 if gp == nil || gp != _m_.curg {
1008 return false
1009 }
1010 if _m_.locks != 0 || _m_.mallocing != 0 || _m_.throwing != 0 || _m_.preemptoff != "" || _m_.dying != 0 {
1011 return false
1012 }
1013 status := readgstatus(gp)
1014 if status&^_Gscan != _Grunning || gp.syscallsp != 0 {
1015 return false
1016 }
1017 if GOOS == "windows" && _m_.libcallsp != 0 {
1018 return false
1019 }
1020 return true
1021 }
1022
1023
1024
1025
1026
1027
1028 func shouldPushSigpanic(gp *g, pc, lr uintptr) bool {
1029 if pc == 0 {
1030
1031
1032
1033
1034
1035 return false
1036 }
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046 if gp.m.incgo || findfunc(pc).valid() {
1047
1048
1049 return true
1050 }
1051 if findfunc(lr).valid() {
1052
1053
1054 return false
1055 }
1056
1057
1058 return true
1059 }
1060
1061
1062
1063
1064
1065
1066
1067
1068 func isAbortPC(pc uintptr) bool {
1069 return pc == funcPC(abort) || ((GOARCH == "arm" || GOARCH == "arm64") && pc == funcPC(abort)+sys.PCQuantum)
1070 }
1071
View as plain text