Source file
src/runtime/panic.go
Documentation: runtime
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 func panicCheckMalloc(err error) {
18 gp := getg()
19 if gp != nil && gp.m != nil && gp.m.mallocing != 0 {
20 throw(string(err.(errorString)))
21 }
22 }
23
24 var indexError = error(errorString("index out of range"))
25
26 func panicindex() {
27 panicCheckMalloc(indexError)
28 panic(indexError)
29 }
30
31 var sliceError = error(errorString("slice bounds out of range"))
32
33 func panicslice() {
34 panicCheckMalloc(sliceError)
35 panic(sliceError)
36 }
37
38 var divideError = error(errorString("integer divide by zero"))
39
40 func panicdivide() {
41 panicCheckMalloc(divideError)
42 panic(divideError)
43 }
44
45 var overflowError = error(errorString("integer overflow"))
46
47 func panicoverflow() {
48 panicCheckMalloc(overflowError)
49 panic(overflowError)
50 }
51
52 var floatError = error(errorString("floating point error"))
53
54 func panicfloat() {
55 panicCheckMalloc(floatError)
56 panic(floatError)
57 }
58
59 var memoryError = error(errorString("invalid memory address or nil pointer dereference"))
60
61 func panicmem() {
62 panicCheckMalloc(memoryError)
63 panic(memoryError)
64 }
65
66 func throwinit() {
67 throw("recursive call during initialization - linker skew")
68 }
69
70
71
72
73 func deferproc(siz int32, fn *funcval) {
74 if getg().m.curg != getg() {
75
76 throw("defer on system stack")
77 }
78
79
80
81
82
83
84 sp := getcallersp(unsafe.Pointer(&siz))
85 argp := uintptr(unsafe.Pointer(&fn)) + unsafe.Sizeof(fn)
86 callerpc := getcallerpc()
87
88 d := newdefer(siz)
89 if d._panic != nil {
90 throw("deferproc: d.panic != nil after newdefer")
91 }
92 d.fn = fn
93 d.pc = callerpc
94 d.sp = sp
95 switch siz {
96 case 0:
97
98 case sys.PtrSize:
99 *(*uintptr)(deferArgs(d)) = *(*uintptr)(unsafe.Pointer(argp))
100 default:
101 memmove(deferArgs(d), unsafe.Pointer(argp), uintptr(siz))
102 }
103
104
105
106
107
108
109
110 return0()
111
112
113 }
114
115
116
117
118
119 const (
120 deferHeaderSize = unsafe.Sizeof(_defer{})
121 minDeferAlloc = (deferHeaderSize + 15) &^ 15
122 minDeferArgs = minDeferAlloc - deferHeaderSize
123 )
124
125
126
127 func deferclass(siz uintptr) uintptr {
128 if siz <= minDeferArgs {
129 return 0
130 }
131 return (siz - minDeferArgs + 15) / 16
132 }
133
134
135 func totaldefersize(siz uintptr) uintptr {
136 if siz <= minDeferArgs {
137 return minDeferAlloc
138 }
139 return deferHeaderSize + siz
140 }
141
142
143
144 func testdefersizes() {
145 var m [len(p{}.deferpool)]int32
146
147 for i := range m {
148 m[i] = -1
149 }
150 for i := uintptr(0); ; i++ {
151 defersc := deferclass(i)
152 if defersc >= uintptr(len(m)) {
153 break
154 }
155 siz := roundupsize(totaldefersize(i))
156 if m[defersc] < 0 {
157 m[defersc] = int32(siz)
158 continue
159 }
160 if m[defersc] != int32(siz) {
161 print("bad defer size class: i=", i, " siz=", siz, " defersc=", defersc, "\n")
162 throw("bad defer size class")
163 }
164 }
165 }
166
167
168
169
170 func deferArgs(d *_defer) unsafe.Pointer {
171 if d.siz == 0 {
172
173 return nil
174 }
175 return add(unsafe.Pointer(d), unsafe.Sizeof(*d))
176 }
177
178 var deferType *_type
179
180 func init() {
181 var x interface{}
182 x = (*_defer)(nil)
183 deferType = (*(**ptrtype)(unsafe.Pointer(&x))).elem
184 }
185
186
187
188
189
190
191
192
193 func newdefer(siz int32) *_defer {
194 var d *_defer
195 sc := deferclass(uintptr(siz))
196 gp := getg()
197 if sc < uintptr(len(p{}.deferpool)) {
198 pp := gp.m.p.ptr()
199 if len(pp.deferpool[sc]) == 0 && sched.deferpool[sc] != nil {
200
201
202 systemstack(func() {
203 lock(&sched.deferlock)
204 for len(pp.deferpool[sc]) < cap(pp.deferpool[sc])/2 && sched.deferpool[sc] != nil {
205 d := sched.deferpool[sc]
206 sched.deferpool[sc] = d.link
207 d.link = nil
208 pp.deferpool[sc] = append(pp.deferpool[sc], d)
209 }
210 unlock(&sched.deferlock)
211 })
212 }
213 if n := len(pp.deferpool[sc]); n > 0 {
214 d = pp.deferpool[sc][n-1]
215 pp.deferpool[sc][n-1] = nil
216 pp.deferpool[sc] = pp.deferpool[sc][:n-1]
217 }
218 }
219 if d == nil {
220
221 systemstack(func() {
222 total := roundupsize(totaldefersize(uintptr(siz)))
223 d = (*_defer)(mallocgc(total, deferType, true))
224 })
225 }
226 d.siz = siz
227 d.link = gp._defer
228 gp._defer = d
229 return d
230 }
231
232
233
234
235
236
237
238
239 func freedefer(d *_defer) {
240 if d._panic != nil {
241 freedeferpanic()
242 }
243 if d.fn != nil {
244 freedeferfn()
245 }
246 sc := deferclass(uintptr(d.siz))
247 if sc >= uintptr(len(p{}.deferpool)) {
248 return
249 }
250 pp := getg().m.p.ptr()
251 if len(pp.deferpool[sc]) == cap(pp.deferpool[sc]) {
252
253
254
255
256 systemstack(func() {
257 var first, last *_defer
258 for len(pp.deferpool[sc]) > cap(pp.deferpool[sc])/2 {
259 n := len(pp.deferpool[sc])
260 d := pp.deferpool[sc][n-1]
261 pp.deferpool[sc][n-1] = nil
262 pp.deferpool[sc] = pp.deferpool[sc][:n-1]
263 if first == nil {
264 first = d
265 } else {
266 last.link = d
267 }
268 last = d
269 }
270 lock(&sched.deferlock)
271 last.link = sched.deferpool[sc]
272 sched.deferpool[sc] = first
273 unlock(&sched.deferlock)
274 })
275 }
276
277
278
279 d.siz = 0
280 d.started = false
281 d.sp = 0
282 d.pc = 0
283 d.fn = nil
284 d._panic = nil
285 d.link = nil
286
287 pp.deferpool[sc] = append(pp.deferpool[sc], d)
288 }
289
290
291
292 func freedeferpanic() {
293
294 throw("freedefer with d._panic != nil")
295 }
296
297 func freedeferfn() {
298
299 throw("freedefer with d.fn != nil")
300 }
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316 func deferreturn(arg0 uintptr) {
317 gp := getg()
318 d := gp._defer
319 if d == nil {
320 return
321 }
322 sp := getcallersp(unsafe.Pointer(&arg0))
323 if d.sp != sp {
324 return
325 }
326
327
328
329
330
331
332
333 switch d.siz {
334 case 0:
335
336 case sys.PtrSize:
337 *(*uintptr)(unsafe.Pointer(&arg0)) = *(*uintptr)(deferArgs(d))
338 default:
339 memmove(unsafe.Pointer(&arg0), deferArgs(d), uintptr(d.siz))
340 }
341 fn := d.fn
342 d.fn = nil
343 gp._defer = d.link
344 freedefer(d)
345 jmpdefer(fn, uintptr(unsafe.Pointer(&arg0)))
346 }
347
348
349
350
351
352
353
354
355
356 func Goexit() {
357
358
359
360 gp := getg()
361 for {
362 d := gp._defer
363 if d == nil {
364 break
365 }
366 if d.started {
367 if d._panic != nil {
368 d._panic.aborted = true
369 d._panic = nil
370 }
371 d.fn = nil
372 gp._defer = d.link
373 freedefer(d)
374 continue
375 }
376 d.started = true
377 reflectcall(nil, unsafe.Pointer(d.fn), deferArgs(d), uint32(d.siz), uint32(d.siz))
378 if gp._defer != d {
379 throw("bad defer entry in Goexit")
380 }
381 d._panic = nil
382 d.fn = nil
383 gp._defer = d.link
384 freedefer(d)
385
386 }
387 goexit1()
388 }
389
390
391
392
393 func preprintpanics(p *_panic) {
394 defer func() {
395 if recover() != nil {
396 throw("panic while printing panic value")
397 }
398 }()
399 for p != nil {
400 switch v := p.arg.(type) {
401 case error:
402 p.arg = v.Error()
403 case stringer:
404 p.arg = v.String()
405 }
406 p = p.link
407 }
408 }
409
410
411
412 func printpanics(p *_panic) {
413 if p.link != nil {
414 printpanics(p.link)
415 print("\t")
416 }
417 print("panic: ")
418
419
420 printany(p.arg)
421 if p.recovered {
422 print(" [recovered]")
423 }
424 print("\n")
425 }
426
427
428 func gopanic(e interface{}) {
429 gp := getg()
430 if gp.m.curg != gp {
431 print("panic: ")
432 printany(e)
433 print("\n")
434 throw("panic on system stack")
435 }
436
437
438
439
440
441 if gp.m.softfloat != 0 {
442 gp.m.locks--
443 gp.m.softfloat = 0
444 throw("panic during softfloat")
445 }
446 if gp.m.mallocing != 0 {
447 print("panic: ")
448 printany(e)
449 print("\n")
450 throw("panic during malloc")
451 }
452 if gp.m.preemptoff != "" {
453 print("panic: ")
454 printany(e)
455 print("\n")
456 print("preempt off reason: ")
457 print(gp.m.preemptoff)
458 print("\n")
459 throw("panic during preemptoff")
460 }
461 if gp.m.locks != 0 {
462 print("panic: ")
463 printany(e)
464 print("\n")
465 throw("panic holding locks")
466 }
467
468 var p _panic
469 p.arg = e
470 p.link = gp._panic
471 gp._panic = (*_panic)(noescape(unsafe.Pointer(&p)))
472
473 atomic.Xadd(&runningPanicDefers, 1)
474
475 for {
476 d := gp._defer
477 if d == nil {
478 break
479 }
480
481
482
483 if d.started {
484 if d._panic != nil {
485 d._panic.aborted = true
486 }
487 d._panic = nil
488 d.fn = nil
489 gp._defer = d.link
490 freedefer(d)
491 continue
492 }
493
494
495
496
497 d.started = true
498
499
500
501
502 d._panic = (*_panic)(noescape(unsafe.Pointer(&p)))
503
504 p.argp = unsafe.Pointer(getargp(0))
505 reflectcall(nil, unsafe.Pointer(d.fn), deferArgs(d), uint32(d.siz), uint32(d.siz))
506 p.argp = nil
507
508
509 if gp._defer != d {
510 throw("bad defer entry in panic")
511 }
512 d._panic = nil
513 d.fn = nil
514 gp._defer = d.link
515
516
517
518
519 pc := d.pc
520 sp := unsafe.Pointer(d.sp)
521 freedefer(d)
522 if p.recovered {
523 atomic.Xadd(&runningPanicDefers, -1)
524
525 gp._panic = p.link
526
527
528 for gp._panic != nil && gp._panic.aborted {
529 gp._panic = gp._panic.link
530 }
531 if gp._panic == nil {
532 gp.sig = 0
533 }
534
535 gp.sigcode0 = uintptr(sp)
536 gp.sigcode1 = pc
537 mcall(recovery)
538 throw("recovery failed")
539 }
540 }
541
542
543
544
545
546 preprintpanics(gp._panic)
547 startpanic()
548
549
550
551 atomic.Xadd(&runningPanicDefers, -1)
552
553 printpanics(gp._panic)
554 dopanic(0)
555 *(*int)(nil) = 0
556 }
557
558
559
560
561
562 func getargp(x int) uintptr {
563
564 return uintptr(noescape(unsafe.Pointer(&x)))
565 }
566
567
568
569
570
571
572
573
574 func gorecover(argp uintptr) interface{} {
575
576
577
578
579
580
581 gp := getg()
582 p := gp._panic
583 if p != nil && !p.recovered && argp == uintptr(p.argp) {
584 p.recovered = true
585 return p.arg
586 }
587 return nil
588 }
589
590
591 func startpanic() {
592 systemstack(startpanic_m)
593 }
594
595
596 func dopanic(unused int) {
597 pc := getcallerpc()
598 sp := getcallersp(unsafe.Pointer(&unused))
599 gp := getg()
600 systemstack(func() {
601 dopanic_m(gp, pc, sp)
602 })
603 *(*int)(nil) = 0
604 }
605
606
607 func sync_throw(s string) {
608 throw(s)
609 }
610
611
612 func throw(s string) {
613 print("fatal error: ", s, "\n")
614 gp := getg()
615 if gp.m.throwing == 0 {
616 gp.m.throwing = 1
617 }
618 startpanic()
619 dopanic(0)
620 *(*int)(nil) = 0
621 }
622
623
624
625
626 var runningPanicDefers uint32
627
628
629
630 var panicking uint32
631
632
633
634 var paniclk mutex
635
636
637
638
639 func recovery(gp *g) {
640
641 sp := gp.sigcode0
642 pc := gp.sigcode1
643
644
645 if sp != 0 && (sp < gp.stack.lo || gp.stack.hi < sp) {
646 print("recover: ", hex(sp), " not in [", hex(gp.stack.lo), ", ", hex(gp.stack.hi), "]\n")
647 throw("bad recovery")
648 }
649
650
651
652
653 gp.sched.sp = sp
654 gp.sched.pc = pc
655 gp.sched.lr = 0
656 gp.sched.ret = 1
657 gogo(&gp.sched)
658 }
659
660
661
662
663
664
665
666 func startpanic_m() {
667 _g_ := getg()
668 if mheap_.cachealloc.size == 0 {
669 print("runtime: panic before malloc heap initialized\n")
670 }
671
672
673
674
675 _g_.m.mallocing++
676
677 switch _g_.m.dying {
678 case 0:
679 _g_.m.dying = 1
680 _g_.writebuf = nil
681 atomic.Xadd(&panicking, 1)
682 lock(&paniclk)
683 if debug.schedtrace > 0 || debug.scheddetail > 0 {
684 schedtrace(true)
685 }
686 freezetheworld()
687 return
688 case 1:
689
690
691 _g_.m.dying = 2
692 print("panic during panic\n")
693 dopanic(0)
694 exit(3)
695 fallthrough
696 case 2:
697
698
699 _g_.m.dying = 3
700 print("stack trace unavailable\n")
701 exit(4)
702 fallthrough
703 default:
704
705 exit(5)
706 }
707 }
708
709 var didothers bool
710 var deadlock mutex
711
712 func dopanic_m(gp *g, pc, sp uintptr) {
713 if gp.sig != 0 {
714 signame := signame(gp.sig)
715 if signame != "" {
716 print("[signal ", signame)
717 } else {
718 print("[signal ", hex(gp.sig))
719 }
720 print(" code=", hex(gp.sigcode0), " addr=", hex(gp.sigcode1), " pc=", hex(gp.sigpc), "]\n")
721 }
722
723 level, all, docrash := gotraceback()
724 _g_ := getg()
725 if level > 0 {
726 if gp != gp.m.curg {
727 all = true
728 }
729 if gp != gp.m.g0 {
730 print("\n")
731 goroutineheader(gp)
732 traceback(pc, sp, 0, gp)
733 } else if level >= 2 || _g_.m.throwing > 0 {
734 print("\nruntime stack:\n")
735 traceback(pc, sp, 0, gp)
736 }
737 if !didothers && all {
738 didothers = true
739 tracebackothers(gp)
740 }
741 }
742 unlock(&paniclk)
743
744 if atomic.Xadd(&panicking, -1) != 0 {
745
746
747
748
749 lock(&deadlock)
750 lock(&deadlock)
751 }
752
753 if docrash {
754 crash()
755 }
756
757 exit(2)
758 }
759
760
761
762
763
764 func canpanic(gp *g) bool {
765
766
767
768 _g_ := getg()
769 _m_ := _g_.m
770
771
772
773
774 if gp == nil || gp != _m_.curg {
775 return false
776 }
777 if _m_.locks-_m_.softfloat != 0 || _m_.mallocing != 0 || _m_.throwing != 0 || _m_.preemptoff != "" || _m_.dying != 0 {
778 return false
779 }
780 status := readgstatus(gp)
781 if status&^_Gscan != _Grunning || gp.syscallsp != 0 {
782 return false
783 }
784 if GOOS == "windows" && _m_.libcallsp != 0 {
785 return false
786 }
787 return true
788 }
789
View as plain text