1// Copyright 2016 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 aix darwin dragonfly freebsd linux netbsd openbsd solaris 6 7package runtime 8 9import ( 10 "unsafe" 11) 12 13// Functions for gccgo to support signal handling. In the gc runtime 14// these are written in OS-specific files and in assembler. 15 16//go:noescape 17//extern sigaction 18func sigaction(signum uint32, act *_sigaction, oact *_sigaction) int32 19 20//go:noescape 21//extern sigprocmask 22func sigprocmask(how int32, set *sigset, oldset *sigset) int32 23 24//go:noescape 25//extern sigfillset 26func sigfillset(set *sigset) int32 27 28//go:noescape 29//extern sigemptyset 30func sigemptyset(set *sigset) int32 31 32//go:noescape 33//extern sigaddset 34func c_sigaddset(set *sigset, signum uint32) int32 35 36//go:noescape 37//extern sigdelset 38func c_sigdelset(set *sigset, signum uint32) int32 39 40//go:noescape 41//extern sigaltstack 42func sigaltstack(ss *_stack_t, oss *_stack_t) int32 43 44//extern raise 45func raise(sig uint32) int32 46 47//extern getpid 48func getpid() _pid_t 49 50//extern kill 51func kill(pid _pid_t, sig uint32) int32 52 53//go:noescape 54//extern setitimer 55func setitimer(which int32, new *_itimerval, old *_itimerval) int32 56 57type sigctxt struct { 58 info *_siginfo_t 59 ctxt unsafe.Pointer 60} 61 62func (c *sigctxt) sigcode() uint64 { 63 if c.info == nil { 64 // This can happen on Solaris 10. We don't know the 65 // code, just avoid a misleading value. 66 return _SI_USER + 1 67 } 68 return uint64(c.info.si_code) 69} 70 71//go:nosplit 72//go:nowritebarrierrec 73func setsig(i uint32, fn uintptr) { 74 var sa _sigaction 75 sa.sa_flags = _SA_SIGINFO | _SA_RESTART 76 77 // For gccgo we do not set SA_ONSTACK for a signal that can 78 // cause a panic. Instead, we trust that the split stack has 79 // enough room to start the signal handler. This is because 80 // otherwise we have no good way to switch back to the 81 // original stack before panicing. 82 if sigtable[i].flags&_SigPanic == 0 { 83 sa.sa_flags |= _SA_ONSTACK 84 } 85 86 sigfillset((*sigset)(unsafe.Pointer(&sa.sa_mask))) 87 setSigactionHandler(&sa, fn) 88 sigaction(i, &sa, nil) 89} 90 91//go:nosplit 92//go:nowritebarrierrec 93func setsigstack(i uint32) { 94 var sa _sigaction 95 sigaction(i, nil, &sa) 96 handler := getSigactionHandler(&sa) 97 if handler == 0 || handler == _SIG_DFL || handler == _SIG_IGN || sa.sa_flags&_SA_ONSTACK != 0 { 98 return 99 } 100 if sigtable[i].flags&_SigPanic != 0 { 101 return 102 } 103 sa.sa_flags |= _SA_ONSTACK 104 sigaction(i, &sa, nil) 105} 106 107//go:nosplit 108//go:nowritebarrierrec 109func getsig(i uint32) uintptr { 110 var sa _sigaction 111 if sigaction(i, nil, &sa) < 0 { 112 // On GNU/Linux glibc rejects attempts to call 113 // sigaction with signal 32 (SIGCANCEL) or 33 (SIGSETXID). 114 if GOOS == "linux" && (i == 32 || i == 33) { 115 return _SIG_DFL 116 } 117 throw("sigaction read failure") 118 } 119 return getSigactionHandler(&sa) 120} 121 122func signalstack(p unsafe.Pointer, n uintptr) 123 124//go:nosplit 125//go:nowritebarrierrec 126func raiseproc(sig uint32) { 127 kill(getpid(), sig) 128} 129 130//go:nosplit 131//go:nowritebarrierrec 132func sigfwd(fn uintptr, sig uint32, info *_siginfo_t, ctx unsafe.Pointer) { 133 f1 := [1]uintptr{fn} 134 f2 := &f1 135 f3 := *(*func(uint32, *_siginfo_t, unsafe.Pointer))(unsafe.Pointer(&f2)) 136 f3(sig, info, ctx) 137} 138 139//go:nosplit 140//go:nowritebarrierrec 141func sigaddset(mask *sigset, i int) { 142 c_sigaddset(mask, uint32(i)) 143} 144 145func sigdelset(mask *sigset, i int) { 146 c_sigdelset(mask, uint32(i)) 147} 148