aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/runtime/signal_gccgo.go
blob: 62fe458803476fd9c1d630b47cc1fc706c108362 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build darwin dragonfly freebsd linux netbsd openbsd solaris

package runtime

import (
	"unsafe"
)

// Functions for gccgo to support signal handling. In the gc runtime
// these are written in OS-specific files and in assembler.

//extern sigaction
func sigaction(signum uint32, act *_sigaction, oact *_sigaction) int32

//extern sigprocmask
func sigprocmask(how int32, set *sigset, oldset *sigset) int32

//extern sigfillset
func sigfillset(set *sigset) int32

//extern sigemptyset
func sigemptyset(set *sigset) int32

//extern sigaddset
func c_sigaddset(set *sigset, signum uint32) int32

//extern sigdelset
func c_sigdelset(set *sigset, signum uint32) int32

//extern sigaltstack
func sigaltstack(ss *_stack_t, oss *_stack_t) int32

//extern raise
func raise(sig uint32) int32

//extern getpid
func getpid() _pid_t

//extern kill
func kill(pid _pid_t, sig uint32) int32

//extern setitimer
func setitimer(which int32, new *_itimerval, old *_itimerval) int32

type siginfo _siginfo_t

type sigTabT struct {
	flags int32
	name  string
}

type sigctxt struct {
	info *siginfo
	ctxt unsafe.Pointer
}

func (c *sigctxt) sigcode() uint64 {
	if c.info == nil {
		// This can happen on Solaris 10.  We don't know the
		// code, just avoid a misleading value.
		return _SI_USER + 1
	}
	return uint64(c.info.si_code)
}

//go:nosplit
//go:nowritebarrierrec
func setsig(i uint32, fn uintptr) {
	var sa _sigaction
	sa.sa_flags = _SA_SIGINFO | _SA_RESTART

	// For gccgo we do not set SA_ONSTACK for a signal that can
	// cause a panic.  Instead, we trust that the split stack has
	// enough room to start the signal handler.  This is because
	// otherwise we have no good way to switch back to the
	// original stack before panicing.
	if sigtable[i].flags&_SigPanic == 0 {
		sa.sa_flags |= _SA_ONSTACK
	}

	sigfillset((*sigset)(unsafe.Pointer(&sa.sa_mask)))
	setSigactionHandler(&sa, fn)
	sigaction(i, &sa, nil)
}

//go:nosplit
//go:nowritebarrierrec
func setsigstack(i uint32) {
	var sa _sigaction
	sigaction(i, nil, &sa)
	handler := getSigactionHandler(&sa)
	if handler == 0 || handler == _SIG_DFL || handler == _SIG_IGN || sa.sa_flags&_SA_ONSTACK != 0 {
		return
	}
	if sigtable[i].flags&_SigPanic != 0 {
		return
	}
	sa.sa_flags |= _SA_ONSTACK
	sigaction(i, &sa, nil)
}

//go:nosplit
//go:nowritebarrierrec
func getsig(i uint32) uintptr {
	var sa _sigaction
	if sigaction(i, nil, &sa) < 0 {
		// On GNU/Linux glibc rejects attempts to call
		// sigaction with signal 32 (SIGCANCEL) or 33 (SIGSETXID).
		if GOOS == "linux" && (i == 32 || i == 33) {
			return _SIG_DFL
		}
		throw("sigaction read failure")
	}
	return getSigactionHandler(&sa)
}

func signalstack(p unsafe.Pointer, n uintptr)

//go:nosplit
//go:nowritebarrierrec
func raiseproc(sig uint32) {
	kill(getpid(), sig)
}

//go:nosplit
//go:nowritebarrierrec
func sigfwd(fn uintptr, sig uint32, info *siginfo, ctx unsafe.Pointer) {
	f1 := &[1]uintptr{fn}
	f2 := *(*func(uint32, *siginfo, unsafe.Pointer))(unsafe.Pointer(&f1))
	f2(sig, info, ctx)
}

//go:nosplit
//go:nowritebarrierrec
func sigaddset(mask *sigset, i int) {
	c_sigaddset(mask, uint32(i))
}

func sigdelset(mask *sigset, i int) {
	c_sigdelset(mask, uint32(i))
}