github.com/q45/go@v0.0.0-20151101211701-a4fb8c13db3f/src/runtime/os3_plan9.go (about) 1 // Copyright 2010 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package runtime 6 7 import "unsafe" 8 9 // May run during STW, so write barriers are not allowed. 10 //go:nowritebarrier 11 func sighandler(_ureg *ureg, note *byte, gp *g) int { 12 _g_ := getg() 13 var t sigTabT 14 var docrash bool 15 var sig int 16 var flags int 17 var level int32 18 19 c := &sigctxt{_ureg} 20 notestr := gostringnocopy(note) 21 22 // The kernel will never pass us a nil note or ureg so we probably 23 // made a mistake somewhere in sigtramp. 24 if _ureg == nil || note == nil { 25 print("sighandler: ureg ", _ureg, " note ", note, "\n") 26 goto Throw 27 } 28 // Check that the note is no more than ERRMAX bytes (including 29 // the trailing NUL). We should never receive a longer note. 30 if len(notestr) > _ERRMAX-1 { 31 print("sighandler: note is longer than ERRMAX\n") 32 goto Throw 33 } 34 // See if the note matches one of the patterns in sigtab. 35 // Notes that do not match any pattern can be handled at a higher 36 // level by the program but will otherwise be ignored. 37 flags = _SigNotify 38 for sig, t = range sigtable { 39 if hasprefix(notestr, t.name) { 40 flags = t.flags 41 break 42 } 43 } 44 if flags&_SigGoExit != 0 { 45 exits((*byte)(add(unsafe.Pointer(note), 9))) // Strip "go: exit " prefix. 46 } 47 if flags&_SigPanic != 0 { 48 // Copy the error string from sigtramp's stack into m->notesig so 49 // we can reliably access it from the panic routines. 50 memmove(unsafe.Pointer(_g_.m.notesig), unsafe.Pointer(note), uintptr(len(notestr)+1)) 51 gp.sig = uint32(sig) 52 gp.sigpc = c.pc() 53 54 pc := uintptr(c.pc()) 55 sp := uintptr(c.sp()) 56 57 // If we don't recognize the PC as code 58 // but we do recognize the top pointer on the stack as code, 59 // then assume this was a call to non-code and treat like 60 // pc == 0, to make unwinding show the context. 61 if pc != 0 && findfunc(pc) == nil && findfunc(*(*uintptr)(unsafe.Pointer(sp))) != nil { 62 pc = 0 63 } 64 65 // Only push sigpanic if PC != 0. 66 // 67 // If PC == 0, probably panicked because of a call to a nil func. 68 // Not pushing that onto SP will make the trace look like a call 69 // to sigpanic instead. (Otherwise the trace will end at 70 // sigpanic and we won't get to see who faulted). 71 if pc != 0 { 72 if regSize > ptrSize { 73 sp -= ptrSize 74 *(*uintptr)(unsafe.Pointer(sp)) = 0 75 } 76 sp -= ptrSize 77 *(*uintptr)(unsafe.Pointer(sp)) = pc 78 c.setsp(sp) 79 } 80 c.setpc(funcPC(sigpanic)) 81 return _NCONT 82 } 83 if flags&_SigNotify != 0 { 84 if sendNote(note) { 85 return _NCONT 86 } 87 } 88 if flags&_SigKill != 0 { 89 goto Exit 90 } 91 if flags&_SigThrow == 0 { 92 return _NCONT 93 } 94 Throw: 95 _g_.m.throwing = 1 96 _g_.m.caughtsig.set(gp) 97 startpanic() 98 print(notestr, "\n") 99 print("PC=", hex(c.pc()), "\n") 100 print("\n") 101 level, _, docrash = gotraceback() 102 if level > 0 { 103 goroutineheader(gp) 104 tracebacktrap(c.pc(), c.sp(), 0, gp) 105 tracebackothers(gp) 106 print("\n") 107 dumpregs(_ureg) 108 } 109 if docrash { 110 crash() 111 } 112 Exit: 113 goexitsall(note) 114 exits(note) 115 return _NDFLT // not reached 116 } 117 118 func sigenable(sig uint32) { 119 } 120 121 func sigdisable(sig uint32) { 122 } 123 124 func sigignore(sig uint32) { 125 } 126 127 func resetcpuprofiler(hz int32) { 128 // TODO: Enable profiling interrupts. 129 getg().m.profilehz = hz 130 }