diff options
author | Yuichi Nishiwaki <yuichi.nishiwaki@gmail.com> | 2019-09-11 02:26:02 +0000 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2019-09-11 03:32:35 +0000 |
commit | 904f046e2ba812e04230c6e5252b3ca87c41e0e1 (patch) | |
tree | 1fa79400ee7e4c2ef7916bff96f094358ee6bc29 /src/runtime/testdata | |
parent | 8ef6d6a8f24354ef167f9dca54ab64e1ea6579f0 (diff) | |
download | go-904f046e2ba812e04230c6e5252b3ca87c41e0e1.tar.gz go-904f046e2ba812e04230c6e5252b3ca87c41e0e1.zip |
runtime: fix crash during VDSO calls on arm
As discussed in #32912, a crash occurs when go runtime calls a VDSO function (say
__vdso_clock_gettime) and a signal arrives to that thread.
Since VDSO functions temporarily destroy the G register (R10),
Go functions asynchronously executed in that thread (i.e. Go's signal
handler) can try to load data from the destroyed G, which causes
segmentation fault.
To fix the issue a guard is inserted in front of sigtrampgo, so that the control escapes from
signal handlers without touching G in case the signal occurred in the VDSO context.
The test case included in the patch is take from discussion in a relevant thread on github:
https://github.com/golang/go/issues/32912#issuecomment-517874531.
This patch not only fixes the issue on AArch64 but also that on 32bit ARM.
Fixes #32912
Change-Id: I657472e54b7aa3c617fabc5019ce63aa4105624a
GitHub-Last-Rev: 28ce42c4a02a060f08c1b0dd1c9a392123fd2ee9
GitHub-Pull-Request: golang/go#34030
Reviewed-on: https://go-review.googlesource.com/c/go/+/192937
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Diffstat (limited to 'src/runtime/testdata')
-rw-r--r-- | src/runtime/testdata/testprog/vdso.go | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/src/runtime/testdata/testprog/vdso.go b/src/runtime/testdata/testprog/vdso.go new file mode 100644 index 0000000000..6036f45bc8 --- /dev/null +++ b/src/runtime/testdata/testprog/vdso.go @@ -0,0 +1,55 @@ +// Copyright 2019 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. + +// Invoke signal hander in the VDSO context (see issue 32912). + +package main + +import ( + "fmt" + "io/ioutil" + "os" + "runtime/pprof" + "time" +) + +func init() { + register("SignalInVDSO", signalInVDSO) +} + +func signalInVDSO() { + f, err := ioutil.TempFile("", "timeprofnow") + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(2) + } + + if err := pprof.StartCPUProfile(f); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(2) + } + + t0 := time.Now() + t1 := t0 + // We should get a profiling signal 100 times a second, + // so running for 1 second should be sufficient. + for t1.Sub(t0) < time.Second { + t1 = time.Now() + } + + pprof.StopCPUProfile() + + name := f.Name() + if err := f.Close(); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(2) + } + + if err := os.Remove(name); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(2) + } + + fmt.Println("success"); +} |