...

Source file src/runtime/os3_plan9.go

     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 (
     8		"runtime/internal/sys"
     9		"unsafe"
    10	)
    11	
    12	// May run during STW, so write barriers are not allowed.
    13	//
    14	//go:nowritebarrierrec
    15	func sighandler(_ureg *ureg, note *byte, gp *g) int {
    16		_g_ := getg()
    17		var t sigTabT
    18		var docrash bool
    19		var sig int
    20		var flags int
    21		var level int32
    22	
    23		c := &sigctxt{_ureg}
    24		notestr := gostringnocopy(note)
    25	
    26		// The kernel will never pass us a nil note or ureg so we probably
    27		// made a mistake somewhere in sigtramp.
    28		if _ureg == nil || note == nil {
    29			print("sighandler: ureg ", _ureg, " note ", note, "\n")
    30			goto Throw
    31		}
    32		// Check that the note is no more than ERRMAX bytes (including
    33		// the trailing NUL). We should never receive a longer note.
    34		if len(notestr) > _ERRMAX-1 {
    35			print("sighandler: note is longer than ERRMAX\n")
    36			goto Throw
    37		}
    38		if isAbortPC(c.pc()) {
    39			// Never turn abort into a panic.
    40			goto Throw
    41		}
    42		// See if the note matches one of the patterns in sigtab.
    43		// Notes that do not match any pattern can be handled at a higher
    44		// level by the program but will otherwise be ignored.
    45		flags = _SigNotify
    46		for sig, t = range sigtable {
    47			if hasPrefix(notestr, t.name) {
    48				flags = t.flags
    49				break
    50			}
    51		}
    52		if flags&_SigPanic != 0 && gp.throwsplit {
    53			// We can't safely sigpanic because it may grow the
    54			// stack. Abort in the signal handler instead.
    55			flags = (flags &^ _SigPanic) | _SigThrow
    56		}
    57		if flags&_SigGoExit != 0 {
    58			exits((*byte)(add(unsafe.Pointer(note), 9))) // Strip "go: exit " prefix.
    59		}
    60		if flags&_SigPanic != 0 {
    61			// Copy the error string from sigtramp's stack into m->notesig so
    62			// we can reliably access it from the panic routines.
    63			memmove(unsafe.Pointer(_g_.m.notesig), unsafe.Pointer(note), uintptr(len(notestr)+1))
    64			gp.sig = uint32(sig)
    65			gp.sigpc = c.pc()
    66	
    67			pc := c.pc()
    68			sp := c.sp()
    69	
    70			// If we don't recognize the PC as code
    71			// but we do recognize the top pointer on the stack as code,
    72			// then assume this was a call to non-code and treat like
    73			// pc == 0, to make unwinding show the context.
    74			if pc != 0 && !findfunc(pc).valid() && findfunc(*(*uintptr)(unsafe.Pointer(sp))).valid() {
    75				pc = 0
    76			}
    77	
    78			// IF LR exists, sigpanictramp must save it to the stack
    79			// before entry to sigpanic so that panics in leaf
    80			// functions are correctly handled. This will smash
    81			// the stack frame but we're not going back there
    82			// anyway.
    83			if usesLR {
    84				c.savelr(c.lr())
    85			}
    86	
    87			// If PC == 0, probably panicked because of a call to a nil func.
    88			// Not faking that as the return address will make the trace look like a call
    89			// to sigpanic instead. (Otherwise the trace will end at
    90			// sigpanic and we won't get to see who faulted).
    91			if pc != 0 {
    92				if usesLR {
    93					c.setlr(pc)
    94				} else {
    95					if sys.RegSize > sys.PtrSize {
    96						sp -= sys.PtrSize
    97						*(*uintptr)(unsafe.Pointer(sp)) = 0
    98					}
    99					sp -= sys.PtrSize
   100					*(*uintptr)(unsafe.Pointer(sp)) = pc
   101					c.setsp(sp)
   102				}
   103			}
   104			if usesLR {
   105				c.setpc(funcPC(sigpanictramp))
   106			} else {
   107				c.setpc(funcPC(sigpanic))
   108			}
   109			return _NCONT
   110		}
   111		if flags&_SigNotify != 0 {
   112			if ignoredNote(note) {
   113				return _NCONT
   114			}
   115			if sendNote(note) {
   116				return _NCONT
   117			}
   118		}
   119		if flags&_SigKill != 0 {
   120			goto Exit
   121		}
   122		if flags&_SigThrow == 0 {
   123			return _NCONT
   124		}
   125	Throw:
   126		_g_.m.throwing = 1
   127		_g_.m.caughtsig.set(gp)
   128		startpanic_m()
   129		print(notestr, "\n")
   130		print("PC=", hex(c.pc()), "\n")
   131		print("\n")
   132		level, _, docrash = gotraceback()
   133		if level > 0 {
   134			goroutineheader(gp)
   135			tracebacktrap(c.pc(), c.sp(), c.lr(), gp)
   136			tracebackothers(gp)
   137			print("\n")
   138			dumpregs(_ureg)
   139		}
   140		if docrash {
   141			crash()
   142		}
   143	Exit:
   144		goexitsall(note)
   145		exits(note)
   146		return _NDFLT // not reached
   147	}
   148	
   149	func sigenable(sig uint32) {
   150	}
   151	
   152	func sigdisable(sig uint32) {
   153	}
   154	
   155	func sigignore(sig uint32) {
   156	}
   157	
   158	func setProcessCPUProfiler(hz int32) {
   159	}
   160	
   161	func setThreadCPUProfiler(hz int32) {
   162		// TODO: Enable profiling interrupts.
   163		getg().m.profilehz = hz
   164	}
   165	
   166	// gsignalStack is unused on Plan 9.
   167	type gsignalStack struct{}
   168	

View as plain text