2016-03-01 15:57:46 -07:00
|
|
|
// Copyright 2010 The Go Authors. All rights reserved.
|
2014-11-21 08:22:18 -07:00
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
package runtime
|
|
|
|
|
|
|
|
import "unsafe"
|
|
|
|
|
2016-05-06 09:26:37 -06:00
|
|
|
type mOS struct {
|
|
|
|
waitsema int32 // semaphore for parking on locks
|
|
|
|
waitsemacount int32
|
|
|
|
waitsemalock int32
|
|
|
|
}
|
|
|
|
|
|
|
|
func nacl_exception_stack(p uintptr, size int32) int32
|
|
|
|
func nacl_exception_handler(fn uintptr, arg unsafe.Pointer) int32
|
|
|
|
func nacl_sem_create(flag int32) int32
|
|
|
|
func nacl_sem_wait(sem int32) int32
|
|
|
|
func nacl_sem_post(sem int32) int32
|
|
|
|
func nacl_mutex_create(flag int32) int32
|
|
|
|
func nacl_mutex_lock(mutex int32) int32
|
|
|
|
func nacl_mutex_trylock(mutex int32) int32
|
|
|
|
func nacl_mutex_unlock(mutex int32) int32
|
|
|
|
func nacl_cond_create(flag int32) int32
|
|
|
|
func nacl_cond_wait(cond, n int32) int32
|
|
|
|
func nacl_cond_signal(cond int32) int32
|
|
|
|
func nacl_cond_broadcast(cond int32) int32
|
|
|
|
|
|
|
|
//go:noescape
|
|
|
|
func nacl_cond_timed_wait_abs(cond, lock int32, ts *timespec) int32
|
|
|
|
func nacl_thread_create(fn uintptr, stk, tls, xx unsafe.Pointer) int32
|
|
|
|
|
|
|
|
//go:noescape
|
|
|
|
func nacl_nanosleep(ts, extra *timespec) int32
|
|
|
|
func nanotime() int64
|
2017-10-16 18:28:29 -06:00
|
|
|
func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) (p unsafe.Pointer, err int)
|
2016-05-06 09:26:37 -06:00
|
|
|
func exit(code int32)
|
|
|
|
func osyield()
|
|
|
|
|
|
|
|
//go:noescape
|
|
|
|
func write(fd uintptr, p unsafe.Pointer, n int32) int32
|
|
|
|
|
|
|
|
//go:linkname os_sigpipe os.sigpipe
|
|
|
|
func os_sigpipe() {
|
|
|
|
throw("too many writes on closed pipe")
|
|
|
|
}
|
|
|
|
|
runtime: minor simplifications to signal code
Change setsig, setsigstack, getsig, raise, raiseproc to take uint32 for
signal number parameter, as that is the type mostly used for signal
numbers. Same for dieFromSignal, sigInstallGoHandler, raisebadsignal.
Remove setsig restart parameter, as it is always either true or
irrelevant.
Don't check the handler in setsigstack, as the only caller does that
anyhow.
Don't bother to convert the handler from sigtramp to sighandler in
getsig, as it will never be called when the handler is sigtramp or
sighandler.
Don't check the return value from rt_sigaction in the GNU/Linux version
of setsigstack; no other setsigstack checks it, and it never fails.
Change-Id: I6bbd677e048a77eddf974dd3d017bc3c560fbd48
Reviewed-on: https://go-review.googlesource.com/29953
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2016-09-27 23:24:51 -06:00
|
|
|
func dieFromSignal(sig uint32) {
|
2016-05-06 09:26:37 -06:00
|
|
|
exit(2)
|
|
|
|
}
|
|
|
|
|
|
|
|
func sigpanic() {
|
|
|
|
g := getg()
|
|
|
|
if !canpanic(g) {
|
|
|
|
throw("unexpected signal during runtime execution")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Native Client only invokes the exception handler for memory faults.
|
|
|
|
g.sig = _SIGSEGV
|
|
|
|
panicmem()
|
|
|
|
}
|
|
|
|
|
runtime: minor simplifications to signal code
Change setsig, setsigstack, getsig, raise, raiseproc to take uint32 for
signal number parameter, as that is the type mostly used for signal
numbers. Same for dieFromSignal, sigInstallGoHandler, raisebadsignal.
Remove setsig restart parameter, as it is always either true or
irrelevant.
Don't check the handler in setsigstack, as the only caller does that
anyhow.
Don't bother to convert the handler from sigtramp to sighandler in
getsig, as it will never be called when the handler is sigtramp or
sighandler.
Don't check the return value from rt_sigaction in the GNU/Linux version
of setsigstack; no other setsigstack checks it, and it never fails.
Change-Id: I6bbd677e048a77eddf974dd3d017bc3c560fbd48
Reviewed-on: https://go-review.googlesource.com/29953
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2016-09-27 23:24:51 -06:00
|
|
|
func raiseproc(sig uint32) {
|
2016-05-06 09:26:37 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// Stubs so tests can link correctly. These should never be called.
|
|
|
|
func open(name *byte, mode, perm int32) int32
|
|
|
|
func closefd(fd int32) int32
|
|
|
|
func read(fd int32, p unsafe.Pointer, n int32) int32
|
|
|
|
|
runtime: use a proper type, sigset, for m.sigmask
Replace the cross platform but unsafe [4]uintptr type with a OS
specific type, sigset. Most OSes already define sigset, and this
change defines a suitable sigset for the OSes that don't (darwin,
openbsd). The OSes that don't use m.sigmask (windows, plan9, nacl)
now defines sigset as the empty type, struct{}.
The gain is strongly typed access to m.sigmask, saving a dynamic
size sanity check and unsafe.Pointer casting. Also, some storage is
saved for each M, since [4]uinptr was conservative for most OSes.
The cost is that OSes that don't need m.sigmask has to define sigset.
completes ./all.bash with GOOS linux, on amd64
completes ./make.bash with GOOSes openbsd, android, plan9, windows,
darwin, solaris, netbsd, freebsd, dragonfly, all amd64.
With GOOS=nacl ./make.bash failed with a seemingly unrelated error.
[Replay of CL 16942 by Elias Naur.]
Change-Id: I98f144d626033ae5318576115ed635415ac71b2c
Reviewed-on: https://go-review.googlesource.com/17033
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
2015-11-17 03:41:06 -07:00
|
|
|
type sigset struct{}
|
|
|
|
|
2014-11-21 08:22:18 -07:00
|
|
|
// Called to initialize a new m (including the bootstrap m).
|
|
|
|
// Called on the parent thread (main thread in case of bootstrap), can allocate memory.
|
|
|
|
func mpreinit(mp *m) {
|
|
|
|
mp.gsignal = malg(32 * 1024)
|
|
|
|
mp.gsignal.m = mp
|
|
|
|
}
|
|
|
|
|
|
|
|
func sigtramp()
|
|
|
|
|
2015-11-13 14:21:01 -07:00
|
|
|
//go:nosplit
|
runtime: don't always unblock all signals
Ian proposed an improved way of handling signals masks in Go, motivated
by a problem where the Android java runtime expects certain signals to
be blocked for all JVM threads. Discussion here
https://groups.google.com/forum/#!topic/golang-dev/_TSCkQHJt6g
Ian's text is used in the following:
A Go program always needs to have the synchronous signals enabled.
These are the signals for which _SigPanic is set in sigtable, namely
SIGSEGV, SIGBUS, SIGFPE.
A Go program that uses the os/signal package, and calls signal.Notify,
needs to have at least one thread which is not blocking that signal,
but it doesn't matter much which one.
Unix programs do not change signal mask across execve. They inherit
signal masks across fork. The shell uses this fact to some extent;
for example, the job control signals (SIGTTIN, SIGTTOU, SIGTSTP) are
blocked for commands run due to backquote quoting or $().
Our current position on signal masks was not thought out. We wandered
into step by step, e.g., http://golang.org/cl/7323067 .
This CL does the following:
Introduce a new platform hook, msigsave, that saves the signal mask of
the current thread to m.sigsave.
Call msigsave from needm and newm.
In minit grab set up the signal mask from m.sigsave and unblock the
essential synchronous signals, and SIGILL, SIGTRAP, SIGPROF, SIGSTKFLT
(for systems that have it).
In unminit, restore the signal mask from m.sigsave.
The first time that os/signal.Notify is called, start a new thread whose
only purpose is to update its signal mask to make sure signals for
signal.Notify are unblocked on at least one thread.
The effect on Go programs will be that if they are invoked with some
non-synchronous signals blocked, those signals will normally be
ignored. Previously, those signals would mostly be ignored. A change
in behaviour will occur for programs started with any of these signals
blocked, if they receive the signal: SIGHUP, SIGINT, SIGQUIT, SIGABRT,
SIGTERM. Previously those signals would always cause a crash (unless
using the os/signal package); with this change, they will be ignored
if the program is started with the signal blocked (and does not use
the os/signal package).
./all.bash completes successfully on linux/amd64.
OpenBSD is missing the implementation.
Change-Id: I188098ba7eb85eae4c14861269cc466f2aa40e8c
Reviewed-on: https://go-review.googlesource.com/10173
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2015-05-18 03:00:24 -06:00
|
|
|
func msigsave(mp *m) {
|
|
|
|
}
|
|
|
|
|
2015-11-13 14:21:01 -07:00
|
|
|
//go:nosplit
|
2016-01-12 16:34:03 -07:00
|
|
|
func msigrestore(sigmask sigset) {
|
2015-11-13 14:21:01 -07:00
|
|
|
}
|
|
|
|
|
2017-06-12 23:36:03 -06:00
|
|
|
//go:nosplit
|
|
|
|
//go:nowritebarrierrec
|
|
|
|
func clearSignalHandlers() {
|
|
|
|
}
|
|
|
|
|
2015-11-13 14:21:01 -07:00
|
|
|
//go:nosplit
|
|
|
|
func sigblock() {
|
|
|
|
}
|
|
|
|
|
2014-11-21 08:22:18 -07:00
|
|
|
// Called to initialize a new m (including the bootstrap m).
|
2016-01-27 13:49:13 -07:00
|
|
|
// Called on the new thread, cannot allocate memory.
|
2014-11-21 08:22:18 -07:00
|
|
|
func minit() {
|
|
|
|
_g_ := getg()
|
|
|
|
|
|
|
|
// Initialize signal handling
|
|
|
|
ret := nacl_exception_stack(_g_.m.gsignal.stack.lo, 32*1024)
|
|
|
|
if ret < 0 {
|
|
|
|
print("runtime: nacl_exception_stack: error ", -ret, "\n")
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = nacl_exception_handler(funcPC(sigtramp), nil)
|
|
|
|
if ret < 0 {
|
|
|
|
print("runtime: nacl_exception_handler: error ", -ret, "\n")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Called from dropm to undo the effect of an minit.
|
|
|
|
func unminit() {
|
|
|
|
}
|
|
|
|
|
|
|
|
func osinit() {
|
|
|
|
ncpu = 1
|
|
|
|
getg().m.procid = 2
|
|
|
|
//nacl_exception_handler(funcPC(sigtramp), nil);
|
2016-07-18 19:40:02 -06:00
|
|
|
physPageSize = 65536
|
2014-11-21 08:22:18 -07:00
|
|
|
}
|
|
|
|
|
2016-05-04 01:42:13 -06:00
|
|
|
func signame(sig uint32) string {
|
|
|
|
if sig >= uint32(len(sigtable)) {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
return sigtable[sig].name
|
|
|
|
}
|
|
|
|
|
2014-11-21 08:22:18 -07:00
|
|
|
func crash() {
|
|
|
|
*(*int32)(nil) = 0
|
|
|
|
}
|
|
|
|
|
2014-12-18 01:26:08 -07:00
|
|
|
//go:noescape
|
|
|
|
func getRandomData([]byte)
|
2014-11-21 08:22:18 -07:00
|
|
|
|
|
|
|
func goenvs() {
|
|
|
|
goenvs_unix()
|
|
|
|
}
|
|
|
|
|
2015-12-26 10:51:59 -07:00
|
|
|
func initsig(preinit bool) {
|
2014-11-21 08:22:18 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
//go:nosplit
|
|
|
|
func usleep(us uint32) {
|
|
|
|
var ts timespec
|
|
|
|
|
|
|
|
ts.tv_sec = int64(us / 1e6)
|
|
|
|
ts.tv_nsec = int32(us%1e6) * 1e3
|
|
|
|
nacl_nanosleep(&ts, nil)
|
|
|
|
}
|
|
|
|
|
|
|
|
func mstart_nacl()
|
|
|
|
|
2015-03-29 08:20:54 -06:00
|
|
|
// May run with m.p==nil, so write barriers are not allowed.
|
2015-03-23 21:13:11 -06:00
|
|
|
//go:nowritebarrier
|
2014-11-21 08:22:18 -07:00
|
|
|
func newosproc(mp *m, stk unsafe.Pointer) {
|
2015-03-23 21:13:11 -06:00
|
|
|
mp.tls[0] = uintptr(unsafe.Pointer(mp.g0))
|
|
|
|
mp.tls[1] = uintptr(unsafe.Pointer(mp))
|
|
|
|
ret := nacl_thread_create(funcPC(mstart_nacl), stk, unsafe.Pointer(&mp.tls[2]), nil)
|
2014-11-21 08:22:18 -07:00
|
|
|
if ret < 0 {
|
|
|
|
print("nacl_thread_create: error ", -ret, "\n")
|
2014-12-27 21:58:00 -07:00
|
|
|
throw("newosproc")
|
2014-11-21 08:22:18 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
runtime: make it possible to exit Go-created threads
Currently, threads created by the runtime exist until the whole
program exits. For #14592 and #20395, we want to be able to exit and
clean up threads created by the runtime. This commit implements that
mechanism.
The main difficulty is how to clean up the g0 stack. In cgo mode and
on Solaris and Windows where the OS manages thread stacks, we simply
arrange to return from mstart and let the system clean up the thread.
If the runtime allocated the g0 stack, then we use a new exitThread
syscall wrapper that arranges to clear a flag in the M once the stack
can safely be reaped and call the thread termination syscall.
exitThread is based on the existing exit1 wrapper, which was always
meant to terminate the calling thread. However, exit1 has never been
used since it was introduced 9 years ago, so it was broken on several
platforms. exitThread also has the additional complication of having
to flag that the stack is unused, which requires some tricks on
platforms that use the stack for syscalls.
This still leaves the problem of how to reap the unused g0 stacks. For
this, we move the M from allm to a new freem list as part of the M
exiting. Later, allocm scans the freem list, finds Ms that are marked
as done with their stack, removes these from the list and frees their
g0 stacks. This also allows these Ms to be garbage collected.
This CL does not yet use any of this functionality. Follow-up CLs
will. Likewise, there are no new tests in this CL because we'll need
follow-up functionality to test it.
Change-Id: Ic851ee74227b6d39c6fc1219fc71b45d3004bc63
Reviewed-on: https://go-review.googlesource.com/46037
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
2017-06-16 13:54:21 -06:00
|
|
|
//go:noescape
|
|
|
|
func exitThread(wait *uint32)
|
|
|
|
|
2014-11-21 08:22:18 -07:00
|
|
|
//go:nosplit
|
2015-10-21 19:36:05 -06:00
|
|
|
func semacreate(mp *m) {
|
|
|
|
if mp.waitsema != 0 {
|
|
|
|
return
|
|
|
|
}
|
2014-11-21 08:22:18 -07:00
|
|
|
systemstack(func() {
|
|
|
|
mu := nacl_mutex_create(0)
|
|
|
|
if mu < 0 {
|
|
|
|
print("nacl_mutex_create: error ", -mu, "\n")
|
2014-12-27 21:58:00 -07:00
|
|
|
throw("semacreate")
|
2014-11-21 08:22:18 -07:00
|
|
|
}
|
|
|
|
c := nacl_cond_create(0)
|
|
|
|
if c < 0 {
|
2015-10-21 19:36:05 -06:00
|
|
|
print("nacl_cond_create: error ", -c, "\n")
|
2014-12-27 21:58:00 -07:00
|
|
|
throw("semacreate")
|
2014-11-21 08:22:18 -07:00
|
|
|
}
|
2015-10-21 19:36:05 -06:00
|
|
|
mp.waitsema = c
|
|
|
|
mp.waitsemalock = mu
|
2014-11-21 08:22:18 -07:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
//go:nosplit
|
|
|
|
func semasleep(ns int64) int32 {
|
|
|
|
var ret int32
|
|
|
|
|
|
|
|
systemstack(func() {
|
|
|
|
_g_ := getg()
|
2015-10-21 19:36:05 -06:00
|
|
|
if nacl_mutex_lock(_g_.m.waitsemalock) < 0 {
|
2014-12-27 21:58:00 -07:00
|
|
|
throw("semasleep")
|
2014-11-21 08:22:18 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
for _g_.m.waitsemacount == 0 {
|
|
|
|
if ns < 0 {
|
2015-10-21 19:36:05 -06:00
|
|
|
if nacl_cond_wait(_g_.m.waitsema, _g_.m.waitsemalock) < 0 {
|
2014-12-27 21:58:00 -07:00
|
|
|
throw("semasleep")
|
2014-11-21 08:22:18 -07:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
var ts timespec
|
|
|
|
end := ns + nanotime()
|
|
|
|
ts.tv_sec = end / 1e9
|
|
|
|
ts.tv_nsec = int32(end % 1e9)
|
2015-10-21 19:36:05 -06:00
|
|
|
r := nacl_cond_timed_wait_abs(_g_.m.waitsema, _g_.m.waitsemalock, &ts)
|
2014-11-21 08:22:18 -07:00
|
|
|
if r == -_ETIMEDOUT {
|
2015-10-21 19:36:05 -06:00
|
|
|
nacl_mutex_unlock(_g_.m.waitsemalock)
|
2014-11-21 08:22:18 -07:00
|
|
|
ret = -1
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if r < 0 {
|
2014-12-27 21:58:00 -07:00
|
|
|
throw("semasleep")
|
2014-11-21 08:22:18 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_g_.m.waitsemacount = 0
|
2015-10-21 19:36:05 -06:00
|
|
|
nacl_mutex_unlock(_g_.m.waitsemalock)
|
2014-11-21 08:22:18 -07:00
|
|
|
ret = 0
|
|
|
|
})
|
|
|
|
return ret
|
|
|
|
}
|
|
|
|
|
|
|
|
//go:nosplit
|
|
|
|
func semawakeup(mp *m) {
|
|
|
|
systemstack(func() {
|
2015-10-21 19:36:05 -06:00
|
|
|
if nacl_mutex_lock(mp.waitsemalock) < 0 {
|
2014-12-27 21:58:00 -07:00
|
|
|
throw("semawakeup")
|
2014-11-21 08:22:18 -07:00
|
|
|
}
|
|
|
|
if mp.waitsemacount != 0 {
|
2014-12-27 21:58:00 -07:00
|
|
|
throw("semawakeup")
|
2014-11-21 08:22:18 -07:00
|
|
|
}
|
|
|
|
mp.waitsemacount = 1
|
2015-10-21 19:36:05 -06:00
|
|
|
nacl_cond_signal(mp.waitsema)
|
|
|
|
nacl_mutex_unlock(mp.waitsemalock)
|
2014-11-21 08:22:18 -07:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2016-03-22 21:11:42 -06:00
|
|
|
// This runs on a foreign stack, without an m or a g. No stack split.
|
|
|
|
//go:nosplit
|
|
|
|
//go:norace
|
|
|
|
//go:nowritebarrierrec
|
|
|
|
func badsignal(sig uintptr) {
|
2016-07-11 17:15:03 -06:00
|
|
|
cgocallback(unsafe.Pointer(funcPC(badsignalgo)), noescape(unsafe.Pointer(&sig)), unsafe.Sizeof(sig), 0)
|
2016-03-22 21:11:42 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
func badsignalgo(sig uintptr) {
|
|
|
|
if !sigsend(uint32(sig)) {
|
|
|
|
// A foreign thread received the signal sig, and the
|
|
|
|
// Go code does not want to handle it.
|
runtime: minor simplifications to signal code
Change setsig, setsigstack, getsig, raise, raiseproc to take uint32 for
signal number parameter, as that is the type mostly used for signal
numbers. Same for dieFromSignal, sigInstallGoHandler, raisebadsignal.
Remove setsig restart parameter, as it is always either true or
irrelevant.
Don't check the handler in setsigstack, as the only caller does that
anyhow.
Don't bother to convert the handler from sigtramp to sighandler in
getsig, as it will never be called when the handler is sigtramp or
sighandler.
Don't check the return value from rt_sigaction in the GNU/Linux version
of setsigstack; no other setsigstack checks it, and it never fails.
Change-Id: I6bbd677e048a77eddf974dd3d017bc3c560fbd48
Reviewed-on: https://go-review.googlesource.com/29953
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2016-09-27 23:24:51 -06:00
|
|
|
raisebadsignal(uint32(sig))
|
2016-03-22 21:11:42 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-01 16:21:55 -07:00
|
|
|
// This runs on a foreign stack, without an m or a g. No stack split.
|
2014-11-21 08:22:18 -07:00
|
|
|
//go:nosplit
|
|
|
|
func badsignal2() {
|
|
|
|
write(2, unsafe.Pointer(&badsignal1[0]), int32(len(badsignal1)))
|
|
|
|
exit(2)
|
|
|
|
}
|
|
|
|
|
|
|
|
var badsignal1 = []byte("runtime: signal received on thread not created by Go.\n")
|
|
|
|
|
runtime: minor simplifications to signal code
Change setsig, setsigstack, getsig, raise, raiseproc to take uint32 for
signal number parameter, as that is the type mostly used for signal
numbers. Same for dieFromSignal, sigInstallGoHandler, raisebadsignal.
Remove setsig restart parameter, as it is always either true or
irrelevant.
Don't check the handler in setsigstack, as the only caller does that
anyhow.
Don't bother to convert the handler from sigtramp to sighandler in
getsig, as it will never be called when the handler is sigtramp or
sighandler.
Don't check the return value from rt_sigaction in the GNU/Linux version
of setsigstack; no other setsigstack checks it, and it never fails.
Change-Id: I6bbd677e048a77eddf974dd3d017bc3c560fbd48
Reviewed-on: https://go-review.googlesource.com/29953
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2016-09-27 23:24:51 -06:00
|
|
|
func raisebadsignal(sig uint32) {
|
2015-07-21 23:34:48 -06:00
|
|
|
badsignal2()
|
|
|
|
}
|
|
|
|
|
2014-11-21 08:22:18 -07:00
|
|
|
func madvise(addr unsafe.Pointer, n uintptr, flags int32) {}
|
|
|
|
func munmap(addr unsafe.Pointer, n uintptr) {}
|
2016-12-06 21:54:41 -07:00
|
|
|
func setProcessCPUProfiler(hz int32) {}
|
|
|
|
func setThreadCPUProfiler(hz int32) {}
|
2014-11-21 08:22:18 -07:00
|
|
|
func sigdisable(uint32) {}
|
|
|
|
func sigenable(uint32) {}
|
2015-01-29 20:37:41 -07:00
|
|
|
func sigignore(uint32) {}
|
2014-11-21 08:22:18 -07:00
|
|
|
func closeonexec(int32) {}
|
|
|
|
|
runtime: restore the Go-allocated signal stack in unminit
Currently, when we minit on a thread that already has an alternate
signal stack (e.g., because the M was an extram being used for a cgo
callback, or to handle a signal on a C thread, or because the
platform's libc always allocates a signal stack like on Android), we
simply drop the Go-allocated gsignal stack on the floor.
This is a problem for Ms on the extram list because those Ms may later
be reused for a different thread that may not have its own alternate
signal stack. On tip, this manifests as a crash in sigaltstack because
we clear the gsignal stack bounds in unminit and later try to use
those cleared bounds when we re-minit that M. On 1.9 and earlier, we
didn't clear the bounds, so this manifests as running more than one
signal handler on the same signal stack, which could lead to arbitrary
memory corruption.
This CL fixes this problem by saving the Go-allocated gsignal stack in
a new field in the m struct when overwriting it with a system-provided
signal stack, and then restoring the original gsignal stack in
unminit.
This CL is designed to be easy to back-port to 1.9. It won't quite
cherry-pick cleanly, but it should be sufficient to simply ignore the
change in mexit (which didn't exist in 1.9).
Now that we always have a place to stash the original signal stack in
the m struct, there are some simplifications we can make to the signal
stack handling. We'll do those in a later CL.
Fixes #22930.
Change-Id: I55c5a6dd9d97532f131146afdef0b216e1433054
Reviewed-on: https://go-review.googlesource.com/81476
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2017-11-30 20:09:35 -07:00
|
|
|
// gsignalStack is unused on nacl.
|
|
|
|
type gsignalStack struct{}
|
|
|
|
|
2014-11-21 08:22:18 -07:00
|
|
|
var writelock uint32 // test-and-set spin lock for write
|
|
|
|
|
|
|
|
/*
|
|
|
|
An attempt at IRT. Doesn't work. See end of sys_nacl_amd64.s.
|
|
|
|
|
|
|
|
void (*nacl_irt_query)(void);
|
|
|
|
|
|
|
|
int8 nacl_irt_basic_v0_1_str[] = "nacl-irt-basic-0.1";
|
|
|
|
void *nacl_irt_basic_v0_1[6]; // exit, gettod, clock, nanosleep, sched_yield, sysconf
|
|
|
|
int32 nacl_irt_basic_v0_1_size = sizeof(nacl_irt_basic_v0_1);
|
|
|
|
|
|
|
|
int8 nacl_irt_memory_v0_3_str[] = "nacl-irt-memory-0.3";
|
|
|
|
void *nacl_irt_memory_v0_3[3]; // mmap, munmap, mprotect
|
|
|
|
int32 nacl_irt_memory_v0_3_size = sizeof(nacl_irt_memory_v0_3);
|
|
|
|
|
|
|
|
int8 nacl_irt_thread_v0_1_str[] = "nacl-irt-thread-0.1";
|
|
|
|
void *nacl_irt_thread_v0_1[3]; // thread_create, thread_exit, thread_nice
|
|
|
|
int32 nacl_irt_thread_v0_1_size = sizeof(nacl_irt_thread_v0_1);
|
|
|
|
*/
|