]> Cypherpunks.ru repositories - gostls13.git/blob - src/runtime/cgo_sigaction.go
cmd/compile/internal/inline: score call sites exposed by inlines
[gostls13.git] / src / runtime / cgo_sigaction.go
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 // Support for sanitizers. See runtime/cgo/sigaction.go.
6
7 //go:build (linux && amd64) || (freebsd && amd64) || (linux && arm64) || (linux && ppc64le)
8
9 package runtime
10
11 import "unsafe"
12
13 // _cgo_sigaction is filled in by runtime/cgo when it is linked into the
14 // program, so it is only non-nil when using cgo.
15 //
16 //go:linkname _cgo_sigaction _cgo_sigaction
17 var _cgo_sigaction unsafe.Pointer
18
19 //go:nosplit
20 //go:nowritebarrierrec
21 func sigaction(sig uint32, new, old *sigactiont) {
22         // racewalk.go avoids adding sanitizing instrumentation to package runtime,
23         // but we might be calling into instrumented C functions here,
24         // so we need the pointer parameters to be properly marked.
25         //
26         // Mark the input as having been written before the call
27         // and the output as read after.
28         if msanenabled && new != nil {
29                 msanwrite(unsafe.Pointer(new), unsafe.Sizeof(*new))
30         }
31         if asanenabled && new != nil {
32                 asanwrite(unsafe.Pointer(new), unsafe.Sizeof(*new))
33         }
34         if _cgo_sigaction == nil || inForkedChild {
35                 sysSigaction(sig, new, old)
36         } else {
37                 // We need to call _cgo_sigaction, which means we need a big enough stack
38                 // for C.  To complicate matters, we may be in libpreinit (before the
39                 // runtime has been initialized) or in an asynchronous signal handler (with
40                 // the current thread in transition between goroutines, or with the g0
41                 // system stack already in use).
42
43                 var ret int32
44
45                 var g *g
46                 if mainStarted {
47                         g = getg()
48                 }
49                 sp := uintptr(unsafe.Pointer(&sig))
50                 switch {
51                 case g == nil:
52                         // No g: we're on a C stack or a signal stack.
53                         ret = callCgoSigaction(uintptr(sig), new, old)
54                 case sp < g.stack.lo || sp >= g.stack.hi:
55                         // We're no longer on g's stack, so we must be handling a signal.  It's
56                         // possible that we interrupted the thread during a transition between g
57                         // and g0, so we should stay on the current stack to avoid corrupting g0.
58                         ret = callCgoSigaction(uintptr(sig), new, old)
59                 default:
60                         // We're running on g's stack, so either we're not in a signal handler or
61                         // the signal handler has set the correct g.  If we're on gsignal or g0,
62                         // systemstack will make the call directly; otherwise, it will switch to
63                         // g0 to ensure we have enough room to call a libc function.
64                         //
65                         // The function literal that we pass to systemstack is not nosplit, but
66                         // that's ok: we'll be running on a fresh, clean system stack so the stack
67                         // check will always succeed anyway.
68                         systemstack(func() {
69                                 ret = callCgoSigaction(uintptr(sig), new, old)
70                         })
71                 }
72
73                 const EINVAL = 22
74                 if ret == EINVAL {
75                         // libc reserves certain signals — normally 32-33 — for pthreads, and
76                         // returns EINVAL for sigaction calls on those signals.  If we get EINVAL,
77                         // fall back to making the syscall directly.
78                         sysSigaction(sig, new, old)
79                 }
80         }
81
82         if msanenabled && old != nil {
83                 msanread(unsafe.Pointer(old), unsafe.Sizeof(*old))
84         }
85         if asanenabled && old != nil {
86                 asanread(unsafe.Pointer(old), unsafe.Sizeof(*old))
87         }
88 }
89
90 // callCgoSigaction calls the sigaction function in the runtime/cgo package
91 // using the GCC calling convention. It is implemented in assembly.
92 //
93 //go:noescape
94 func callCgoSigaction(sig uintptr, new, old *sigactiont) int32