...
Run Format

Source file src/runtime/signal_unix.go

     1	// Copyright 2012 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	// +build darwin dragonfly freebsd linux netbsd openbsd solaris
     6	
     7	package runtime
     8	
     9	import (
    10		"runtime/internal/sys"
    11		"unsafe"
    12	)
    13	
    14	//go:linkname os_sigpipe os.sigpipe
    15	func os_sigpipe() {
    16		systemstack(sigpipe)
    17	}
    18	
    19	func signame(sig uint32) string {
    20		if sig >= uint32(len(sigtable)) {
    21			return ""
    22		}
    23		return sigtable[sig].name
    24	}
    25	
    26	const (
    27		_SIG_DFL uintptr = 0
    28		_SIG_IGN uintptr = 1
    29	)
    30	
    31	// Stores the signal handlers registered before Go installed its own.
    32	// These signal handlers will be invoked in cases where Go doesn't want to
    33	// handle a particular signal (e.g., signal occurred on a non-Go thread).
    34	// See sigfwdgo() for more information on when the signals are forwarded.
    35	//
    36	// Signal forwarding is currently available only on Darwin and Linux.
    37	var fwdSig [_NSIG]uintptr
    38	
    39	// channels for synchronizing signal mask updates with the signal mask
    40	// thread
    41	var (
    42		disableSigChan  chan uint32
    43		enableSigChan   chan uint32
    44		maskUpdatedChan chan struct{}
    45	)
    46	
    47	func init() {
    48		// _NSIG is the number of signals on this operating system.
    49		// sigtable should describe what to do for all the possible signals.
    50		if len(sigtable) != _NSIG {
    51			print("runtime: len(sigtable)=", len(sigtable), " _NSIG=", _NSIG, "\n")
    52			throw("bad sigtable len")
    53		}
    54	}
    55	
    56	var signalsOK bool
    57	
    58	// Initialize signals.
    59	// Called by libpreinit so runtime may not be initialized.
    60	//go:nosplit
    61	//go:nowritebarrierrec
    62	func initsig(preinit bool) {
    63		if !preinit {
    64			// It's now OK for signal handlers to run.
    65			signalsOK = true
    66		}
    67	
    68		// For c-archive/c-shared this is called by libpreinit with
    69		// preinit == true.
    70		if (isarchive || islibrary) && !preinit {
    71			return
    72		}
    73	
    74		for i := uint32(0); i < _NSIG; i++ {
    75			t := &sigtable[i]
    76			if t.flags == 0 || t.flags&_SigDefault != 0 {
    77				continue
    78			}
    79			fwdSig[i] = getsig(i)
    80	
    81			if !sigInstallGoHandler(i) {
    82				// Even if we are not installing a signal handler,
    83				// set SA_ONSTACK if necessary.
    84				if fwdSig[i] != _SIG_DFL && fwdSig[i] != _SIG_IGN {
    85					setsigstack(i)
    86				}
    87				continue
    88			}
    89	
    90			t.flags |= _SigHandling
    91			setsig(i, funcPC(sighandler))
    92		}
    93	}
    94	
    95	//go:nosplit
    96	//go:nowritebarrierrec
    97	func sigInstallGoHandler(sig uint32) bool {
    98		// For some signals, we respect an inherited SIG_IGN handler
    99		// rather than insist on installing our own default handler.
   100		// Even these signals can be fetched using the os/signal package.
   101		switch sig {
   102		case _SIGHUP, _SIGINT:
   103			if fwdSig[sig] == _SIG_IGN {
   104				return false
   105			}
   106		}
   107	
   108		t := &sigtable[sig]
   109		if t.flags&_SigSetStack != 0 {
   110			return false
   111		}
   112	
   113		// When built using c-archive or c-shared, only install signal
   114		// handlers for synchronous signals.
   115		if (isarchive || islibrary) && t.flags&_SigPanic == 0 {
   116			return false
   117		}
   118	
   119		return true
   120	}
   121	
   122	func sigenable(sig uint32) {
   123		if sig >= uint32(len(sigtable)) {
   124			return
   125		}
   126	
   127		t := &sigtable[sig]
   128		if t.flags&_SigNotify != 0 {
   129			ensureSigM()
   130			enableSigChan <- sig
   131			<-maskUpdatedChan
   132			if t.flags&_SigHandling == 0 {
   133				t.flags |= _SigHandling
   134				fwdSig[sig] = getsig(sig)
   135				setsig(sig, funcPC(sighandler))
   136			}
   137		}
   138	}
   139	
   140	func sigdisable(sig uint32) {
   141		if sig >= uint32(len(sigtable)) {
   142			return
   143		}
   144	
   145		t := &sigtable[sig]
   146		if t.flags&_SigNotify != 0 {
   147			ensureSigM()
   148			disableSigChan <- sig
   149			<-maskUpdatedChan
   150	
   151			// If initsig does not install a signal handler for a
   152			// signal, then to go back to the state before Notify
   153			// we should remove the one we installed.
   154			if !sigInstallGoHandler(sig) {
   155				t.flags &^= _SigHandling
   156				setsig(sig, fwdSig[sig])
   157			}
   158		}
   159	}
   160	
   161	func sigignore(sig uint32) {
   162		if sig >= uint32(len(sigtable)) {
   163			return
   164		}
   165	
   166		t := &sigtable[sig]
   167		if t.flags&_SigNotify != 0 {
   168			t.flags &^= _SigHandling
   169			setsig(sig, _SIG_IGN)
   170		}
   171	}
   172	
   173	func resetcpuprofiler(hz int32) {
   174		var it itimerval
   175		if hz == 0 {
   176			setitimer(_ITIMER_PROF, &it, nil)
   177		} else {
   178			it.it_interval.tv_sec = 0
   179			it.it_interval.set_usec(1000000 / hz)
   180			it.it_value = it.it_interval
   181			setitimer(_ITIMER_PROF, &it, nil)
   182		}
   183		_g_ := getg()
   184		_g_.m.profilehz = hz
   185	}
   186	
   187	func sigpipe() {
   188		if sigsend(_SIGPIPE) {
   189			return
   190		}
   191		dieFromSignal(_SIGPIPE)
   192	}
   193	
   194	// sigtrampgo is called from the signal handler function, sigtramp,
   195	// written in assembly code.
   196	// This is called by the signal handler, and the world may be stopped.
   197	//go:nosplit
   198	//go:nowritebarrierrec
   199	func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) {
   200		if sigfwdgo(sig, info, ctx) {
   201			return
   202		}
   203		g := getg()
   204		if g == nil {
   205			c := &sigctxt{info, ctx}
   206			if sig == _SIGPROF {
   207				sigprofNonGoPC(c.sigpc())
   208				return
   209			}
   210			badsignal(uintptr(sig), c)
   211			return
   212		}
   213	
   214		// If some non-Go code called sigaltstack, adjust.
   215		setStack := false
   216		var gsignalStack gsignalStack
   217		sp := uintptr(unsafe.Pointer(&sig))
   218		if sp < g.m.gsignal.stack.lo || sp >= g.m.gsignal.stack.hi {
   219			if sp >= g.m.g0.stack.lo && sp < g.m.g0.stack.hi {
   220				// The signal was delivered on the g0 stack.
   221				// This can happen when linked with C code
   222				// using the thread sanitizer, which collects
   223				// signals then delivers them itself by calling
   224				// the signal handler directly when C code,
   225				// including C code called via cgo, calls a
   226				// TSAN-intercepted function such as malloc.
   227				st := stackt{ss_size: g.m.g0.stack.hi - g.m.g0.stack.lo}
   228				setSignalstackSP(&st, g.m.g0.stack.lo)
   229				setGsignalStack(&st, &gsignalStack)
   230				g.m.gsignal.stktopsp = getcallersp(unsafe.Pointer(&sig))
   231				setStack = true
   232			} else {
   233				var st stackt
   234				sigaltstack(nil, &st)
   235				if st.ss_flags&_SS_DISABLE != 0 {
   236					setg(nil)
   237					needm(0)
   238					noSignalStack(sig)
   239					dropm()
   240				}
   241				stsp := uintptr(unsafe.Pointer(st.ss_sp))
   242				if sp < stsp || sp >= stsp+st.ss_size {
   243					setg(nil)
   244					needm(0)
   245					sigNotOnStack(sig)
   246					dropm()
   247				}
   248				setGsignalStack(&st, &gsignalStack)
   249				g.m.gsignal.stktopsp = getcallersp(unsafe.Pointer(&sig))
   250				setStack = true
   251			}
   252		}
   253	
   254		setg(g.m.gsignal)
   255		c := &sigctxt{info, ctx}
   256		c.fixsigcode(sig)
   257		sighandler(sig, info, ctx, g)
   258		setg(g)
   259		if setStack {
   260			restoreGsignalStack(&gsignalStack)
   261		}
   262	}
   263	
   264	// sigpanic turns a synchronous signal into a run-time panic.
   265	// If the signal handler sees a synchronous panic, it arranges the
   266	// stack to look like the function where the signal occurred called
   267	// sigpanic, sets the signal's PC value to sigpanic, and returns from
   268	// the signal handler. The effect is that the program will act as
   269	// though the function that got the signal simply called sigpanic
   270	// instead.
   271	func sigpanic() {
   272		g := getg()
   273		if !canpanic(g) {
   274			throw("unexpected signal during runtime execution")
   275		}
   276	
   277		switch g.sig {
   278		case _SIGBUS:
   279			if g.sigcode0 == _BUS_ADRERR && g.sigcode1 < 0x1000 {
   280				panicmem()
   281			}
   282			// Support runtime/debug.SetPanicOnFault.
   283			if g.paniconfault {
   284				panicmem()
   285			}
   286			print("unexpected fault address ", hex(g.sigcode1), "\n")
   287			throw("fault")
   288		case _SIGSEGV:
   289			if (g.sigcode0 == 0 || g.sigcode0 == _SEGV_MAPERR || g.sigcode0 == _SEGV_ACCERR) && g.sigcode1 < 0x1000 {
   290				panicmem()
   291			}
   292			// Support runtime/debug.SetPanicOnFault.
   293			if g.paniconfault {
   294				panicmem()
   295			}
   296			print("unexpected fault address ", hex(g.sigcode1), "\n")
   297			throw("fault")
   298		case _SIGFPE:
   299			switch g.sigcode0 {
   300			case _FPE_INTDIV:
   301				panicdivide()
   302			case _FPE_INTOVF:
   303				panicoverflow()
   304			}
   305			panicfloat()
   306		}
   307	
   308		if g.sig >= uint32(len(sigtable)) {
   309			// can't happen: we looked up g.sig in sigtable to decide to call sigpanic
   310			throw("unexpected signal value")
   311		}
   312		panic(errorString(sigtable[g.sig].name))
   313	}
   314	
   315	// dieFromSignal kills the program with a signal.
   316	// This provides the expected exit status for the shell.
   317	// This is only called with fatal signals expected to kill the process.
   318	//go:nosplit
   319	//go:nowritebarrierrec
   320	func dieFromSignal(sig uint32) {
   321		setsig(sig, _SIG_DFL)
   322		unblocksig(sig)
   323		raise(sig)
   324	
   325		// That should have killed us. On some systems, though, raise
   326		// sends the signal to the whole process rather than to just
   327		// the current thread, which means that the signal may not yet
   328		// have been delivered. Give other threads a chance to run and
   329		// pick up the signal.
   330		osyield()
   331		osyield()
   332		osyield()
   333	
   334		// If we are still somehow running, just exit with the wrong status.
   335		exit(2)
   336	}
   337	
   338	// raisebadsignal is called when a signal is received on a non-Go
   339	// thread, and the Go program does not want to handle it (that is, the
   340	// program has not called os/signal.Notify for the signal).
   341	func raisebadsignal(sig uint32, c *sigctxt) {
   342		if sig == _SIGPROF {
   343			// Ignore profiling signals that arrive on non-Go threads.
   344			return
   345		}
   346	
   347		var handler uintptr
   348		if sig >= _NSIG {
   349			handler = _SIG_DFL
   350		} else {
   351			handler = fwdSig[sig]
   352		}
   353	
   354		// Reset the signal handler and raise the signal.
   355		// We are currently running inside a signal handler, so the
   356		// signal is blocked. We need to unblock it before raising the
   357		// signal, or the signal we raise will be ignored until we return
   358		// from the signal handler. We know that the signal was unblocked
   359		// before entering the handler, or else we would not have received
   360		// it. That means that we don't have to worry about blocking it
   361		// again.
   362		unblocksig(sig)
   363		setsig(sig, handler)
   364	
   365		// If we're linked into a non-Go program we want to try to
   366		// avoid modifying the original context in which the signal
   367		// was raised. If the handler is the default, we know it
   368		// is non-recoverable, so we don't have to worry about
   369		// re-installing sighandler. At this point we can just
   370		// return and the signal will be re-raised and caught by
   371		// the default handler with the correct context.
   372		if (isarchive || islibrary) && handler == _SIG_DFL && c.sigcode() != _SI_USER {
   373			return
   374		}
   375	
   376		raise(sig)
   377	
   378		// Give the signal a chance to be delivered.
   379		// In almost all real cases the program is about to crash,
   380		// so sleeping here is not a waste of time.
   381		usleep(1000)
   382	
   383		// If the signal didn't cause the program to exit, restore the
   384		// Go signal handler and carry on.
   385		//
   386		// We may receive another instance of the signal before we
   387		// restore the Go handler, but that is not so bad: we know
   388		// that the Go program has been ignoring the signal.
   389		setsig(sig, funcPC(sighandler))
   390	}
   391	
   392	func crash() {
   393		if GOOS == "darwin" {
   394			// OS X core dumps are linear dumps of the mapped memory,
   395			// from the first virtual byte to the last, with zeros in the gaps.
   396			// Because of the way we arrange the address space on 64-bit systems,
   397			// this means the OS X core file will be >128 GB and even on a zippy
   398			// workstation can take OS X well over an hour to write (uninterruptible).
   399			// Save users from making that mistake.
   400			if sys.PtrSize == 8 {
   401				return
   402			}
   403		}
   404	
   405		dieFromSignal(_SIGABRT)
   406	}
   407	
   408	// ensureSigM starts one global, sleeping thread to make sure at least one thread
   409	// is available to catch signals enabled for os/signal.
   410	func ensureSigM() {
   411		if maskUpdatedChan != nil {
   412			return
   413		}
   414		maskUpdatedChan = make(chan struct{})
   415		disableSigChan = make(chan uint32)
   416		enableSigChan = make(chan uint32)
   417		go func() {
   418			// Signal masks are per-thread, so make sure this goroutine stays on one
   419			// thread.
   420			LockOSThread()
   421			defer UnlockOSThread()
   422			// The sigBlocked mask contains the signals not active for os/signal,
   423			// initially all signals except the essential. When signal.Notify()/Stop is called,
   424			// sigenable/sigdisable in turn notify this thread to update its signal
   425			// mask accordingly.
   426			sigBlocked := sigset_all
   427			for i := range sigtable {
   428				if sigtable[i].flags&_SigUnblock != 0 {
   429					sigdelset(&sigBlocked, i)
   430				}
   431			}
   432			sigprocmask(_SIG_SETMASK, &sigBlocked, nil)
   433			for {
   434				select {
   435				case sig := <-enableSigChan:
   436					if sig > 0 {
   437						sigdelset(&sigBlocked, int(sig))
   438					}
   439				case sig := <-disableSigChan:
   440					if sig > 0 {
   441						sigaddset(&sigBlocked, int(sig))
   442					}
   443				}
   444				sigprocmask(_SIG_SETMASK, &sigBlocked, nil)
   445				maskUpdatedChan <- struct{}{}
   446			}
   447		}()
   448	}
   449	
   450	// This is called when we receive a signal when there is no signal stack.
   451	// This can only happen if non-Go code calls sigaltstack to disable the
   452	// signal stack.
   453	func noSignalStack(sig uint32) {
   454		println("signal", sig, "received on thread with no signal stack")
   455		throw("non-Go code disabled sigaltstack")
   456	}
   457	
   458	// This is called if we receive a signal when there is a signal stack
   459	// but we are not on it. This can only happen if non-Go code called
   460	// sigaction without setting the SS_ONSTACK flag.
   461	func sigNotOnStack(sig uint32) {
   462		println("signal", sig, "received but handler not on signal stack")
   463		throw("non-Go code set up signal handler without SA_ONSTACK flag")
   464	}
   465	
   466	// This runs on a foreign stack, without an m or a g. No stack split.
   467	//go:nosplit
   468	//go:norace
   469	//go:nowritebarrierrec
   470	func badsignal(sig uintptr, c *sigctxt) {
   471		needm(0)
   472		if !sigsend(uint32(sig)) {
   473			// A foreign thread received the signal sig, and the
   474			// Go code does not want to handle it.
   475			raisebadsignal(uint32(sig), c)
   476		}
   477		dropm()
   478	}
   479	
   480	//go:noescape
   481	func sigfwd(fn uintptr, sig uint32, info *siginfo, ctx unsafe.Pointer)
   482	
   483	// Determines if the signal should be handled by Go and if not, forwards the
   484	// signal to the handler that was installed before Go's. Returns whether the
   485	// signal was forwarded.
   486	// This is called by the signal handler, and the world may be stopped.
   487	//go:nosplit
   488	//go:nowritebarrierrec
   489	func sigfwdgo(sig uint32, info *siginfo, ctx unsafe.Pointer) bool {
   490		if sig >= uint32(len(sigtable)) {
   491			return false
   492		}
   493		fwdFn := fwdSig[sig]
   494	
   495		if !signalsOK {
   496			// The only way we can get here is if we are in a
   497			// library or archive, we installed a signal handler
   498			// at program startup, but the Go runtime has not yet
   499			// been initialized.
   500			if fwdFn == _SIG_DFL {
   501				dieFromSignal(sig)
   502			} else {
   503				sigfwd(fwdFn, sig, info, ctx)
   504			}
   505			return true
   506		}
   507	
   508		flags := sigtable[sig].flags
   509	
   510		// If there is no handler to forward to, no need to forward.
   511		if fwdFn == _SIG_DFL {
   512			return false
   513		}
   514	
   515		// If we aren't handling the signal, forward it.
   516		if flags&_SigHandling == 0 {
   517			sigfwd(fwdFn, sig, info, ctx)
   518			return true
   519		}
   520	
   521		// Only forward synchronous signals.
   522		c := &sigctxt{info, ctx}
   523		if c.sigcode() == _SI_USER || flags&_SigPanic == 0 {
   524			return false
   525		}
   526		// Determine if the signal occurred inside Go code. We test that:
   527		//   (1) we were in a goroutine (i.e., m.curg != nil), and
   528		//   (2) we weren't in CGO (i.e., m.curg.syscallsp == 0).
   529		g := getg()
   530		if g != nil && g.m != nil && g.m.curg != nil && g.m.curg.syscallsp == 0 {
   531			return false
   532		}
   533		// Signal not handled by Go, forward it.
   534		if fwdFn != _SIG_IGN {
   535			sigfwd(fwdFn, sig, info, ctx)
   536		}
   537		return true
   538	}
   539	
   540	// msigsave saves the current thread's signal mask into mp.sigmask.
   541	// This is used to preserve the non-Go signal mask when a non-Go
   542	// thread calls a Go function.
   543	// This is nosplit and nowritebarrierrec because it is called by needm
   544	// which may be called on a non-Go thread with no g available.
   545	//go:nosplit
   546	//go:nowritebarrierrec
   547	func msigsave(mp *m) {
   548		sigprocmask(_SIG_SETMASK, nil, &mp.sigmask)
   549	}
   550	
   551	// msigrestore sets the current thread's signal mask to sigmask.
   552	// This is used to restore the non-Go signal mask when a non-Go thread
   553	// calls a Go function.
   554	// This is nosplit and nowritebarrierrec because it is called by dropm
   555	// after g has been cleared.
   556	//go:nosplit
   557	//go:nowritebarrierrec
   558	func msigrestore(sigmask sigset) {
   559		sigprocmask(_SIG_SETMASK, &sigmask, nil)
   560	}
   561	
   562	// sigblock blocks all signals in the current thread's signal mask.
   563	// This is used to block signals while setting up and tearing down g
   564	// when a non-Go thread calls a Go function.
   565	// The OS-specific code is expected to define sigset_all.
   566	// This is nosplit and nowritebarrierrec because it is called by needm
   567	// which may be called on a non-Go thread with no g available.
   568	//go:nosplit
   569	//go:nowritebarrierrec
   570	func sigblock() {
   571		sigprocmask(_SIG_SETMASK, &sigset_all, nil)
   572	}
   573	
   574	// unblocksig removes sig from the current thread's signal mask.
   575	// This is nosplit and nowritebarrierrec because it is called from
   576	// dieFromSignal, which can be called by sigfwdgo while running in the
   577	// signal handler, on the signal stack, with no g available.
   578	//go:nosplit
   579	//go:nowritebarrierrec
   580	func unblocksig(sig uint32) {
   581		var set sigset
   582		sigaddset(&set, int(sig))
   583		sigprocmask(_SIG_UNBLOCK, &set, nil)
   584	}
   585	
   586	// minitSignals is called when initializing a new m to set the
   587	// thread's alternate signal stack and signal mask.
   588	func minitSignals() {
   589		minitSignalStack()
   590		minitSignalMask()
   591	}
   592	
   593	// minitSignalStack is called when initializing a new m to set the
   594	// alternate signal stack. If the alternate signal stack is not set
   595	// for the thread (the normal case) then set the alternate signal
   596	// stack to the gsignal stack. If the alternate signal stack is set
   597	// for the thread (the case when a non-Go thread sets the alternate
   598	// signal stack and then calls a Go function) then set the gsignal
   599	// stack to the alternate signal stack. Record which choice was made
   600	// in newSigstack, so that it can be undone in unminit.
   601	func minitSignalStack() {
   602		_g_ := getg()
   603		var st stackt
   604		sigaltstack(nil, &st)
   605		if st.ss_flags&_SS_DISABLE != 0 {
   606			signalstack(&_g_.m.gsignal.stack)
   607			_g_.m.newSigstack = true
   608		} else {
   609			setGsignalStack(&st, nil)
   610			_g_.m.newSigstack = false
   611		}
   612	}
   613	
   614	// minitSignalMask is called when initializing a new m to set the
   615	// thread's signal mask. When this is called all signals have been
   616	// blocked for the thread.  This starts with m.sigmask, which was set
   617	// either from initSigmask for a newly created thread or by calling
   618	// msigsave if this is a non-Go thread calling a Go function. It
   619	// removes all essential signals from the mask, thus causing those
   620	// signals to not be blocked. Then it sets the thread's signal mask.
   621	// After this is called the thread can receive signals.
   622	func minitSignalMask() {
   623		nmask := getg().m.sigmask
   624		for i := range sigtable {
   625			if sigtable[i].flags&_SigUnblock != 0 {
   626				sigdelset(&nmask, i)
   627			}
   628		}
   629		sigprocmask(_SIG_SETMASK, &nmask, nil)
   630	}
   631	
   632	// unminitSignals is called from dropm, via unminit, to undo the
   633	// effect of calling minit on a non-Go thread.
   634	//go:nosplit
   635	func unminitSignals() {
   636		if getg().m.newSigstack {
   637			st := stackt{ss_flags: _SS_DISABLE}
   638			sigaltstack(&st, nil)
   639		}
   640	}
   641	
   642	// gsignalStack saves the fields of the gsignal stack changed by
   643	// setGsignalStack.
   644	type gsignalStack struct {
   645		stack       stack
   646		stackguard0 uintptr
   647		stackguard1 uintptr
   648		stackAlloc  uintptr
   649		stktopsp    uintptr
   650	}
   651	
   652	// setGsignalStack sets the gsignal stack of the current m to an
   653	// alternate signal stack returned from the sigaltstack system call.
   654	// It saves the old values in *old for use by restoreGsignalStack.
   655	// This is used when handling a signal if non-Go code has set the
   656	// alternate signal stack.
   657	//go:nosplit
   658	//go:nowritebarrierrec
   659	func setGsignalStack(st *stackt, old *gsignalStack) {
   660		g := getg()
   661		if old != nil {
   662			old.stack = g.m.gsignal.stack
   663			old.stackguard0 = g.m.gsignal.stackguard0
   664			old.stackguard1 = g.m.gsignal.stackguard1
   665			old.stackAlloc = g.m.gsignal.stackAlloc
   666			old.stktopsp = g.m.gsignal.stktopsp
   667		}
   668		stsp := uintptr(unsafe.Pointer(st.ss_sp))
   669		g.m.gsignal.stack.lo = stsp
   670		g.m.gsignal.stack.hi = stsp + st.ss_size
   671		g.m.gsignal.stackguard0 = stsp + _StackGuard
   672		g.m.gsignal.stackguard1 = stsp + _StackGuard
   673		g.m.gsignal.stackAlloc = st.ss_size
   674	}
   675	
   676	// restoreGsignalStack restores the gsignal stack to the value it had
   677	// before entering the signal handler.
   678	//go:nosplit
   679	//go:nowritebarrierrec
   680	func restoreGsignalStack(st *gsignalStack) {
   681		gp := getg().m.gsignal
   682		gp.stack = st.stack
   683		gp.stackguard0 = st.stackguard0
   684		gp.stackguard1 = st.stackguard1
   685		gp.stackAlloc = st.stackAlloc
   686		gp.stktopsp = st.stktopsp
   687	}
   688	
   689	// signalstack sets the current thread's alternate signal stack to s.
   690	//go:nosplit
   691	func signalstack(s *stack) {
   692		st := stackt{ss_size: s.hi - s.lo}
   693		setSignalstackSP(&st, s.lo)
   694		sigaltstack(&st, nil)
   695	}
   696	
   697	// setsigsegv is used on darwin/arm{,64} to fake a segmentation fault.
   698	//go:nosplit
   699	func setsigsegv(pc uintptr) {
   700		g := getg()
   701		g.sig = _SIGSEGV
   702		g.sigpc = pc
   703		g.sigcode0 = _SEGV_MAPERR
   704		g.sigcode1 = 0 // TODO: emulate si_addr
   705	}
   706	

View as plain text