Currently, if sigprof determines that the G is in user code (not cgo or libcall code), it will only traceback the G stack if it can acquire the stack barrier lock. However, it has no such restriction if the G is in cgo or libcall code. Because cgo calls count as syscalls, stack scanning and stack barrier installation can occur during a cgo call, which means sigprof could attempt to traceback a G in a cgo call while scanstack is installing stack barriers in that G's stack. As a result, the following sequence of events can cause the sigprof traceback to panic with "missed stack barrier": 1. M1: G1 performs a Cgo call (which, on Windows, is any system call, which could explain why this is easier to reproduce on Windows). 2. M1: The Cgo call puts G1 into _Gsyscall state. 3. M2: GC starts a scan of G1's stack. It puts G1 in to _Gscansyscall and acquires the stack barrier lock. 4. M3: A profiling signal comes in. On Windows this is a global (though I don't think this matters), so the runtime stops M1 and calls sigprof for G1. 5. M3: sigprof fails to acquire the stack barrier lock (because the GC's stack scan holds it). 6. M3: sigprof observes that G1 is in a Cgo call, so it calls gentraceback on G1 with its Cgo transition point. 7. M3: gentraceback on G1 grabs the currently empty g.stkbar slice. 8. M2: GC finishes scanning G1's stack and installing stack barriers. 9. M3: gentraceback encounters one of the just-installed stack barriers and panics. This commit fixes this by only allowing cgo tracebacks if sigprof can acquire the stack barrier lock, just like in the regular user traceback case. For good measure, we put the same constraint on libcall tracebacks. This case is probably already safe because, unlike cgo calls, libcalls leave the G in _Grunning and prevent reaching a safe point, so scanstack cannot run during a libcall. However, this also means that sigprof will always acquire the stack barrier lock without contention, so there's no cost to adding this constraint to libcall tracebacks. Fixes #12528. For 1.5.3 (will require some backporting). Change-Id: Ia5a4b8e3d66b23b02ffcd54c6315c81055c0cec2 Reviewed-on: https://go-review.googlesource.com/18023 Run-TryBot: Austin Clements <austin@google.com> Reviewed-by: Russ Cox <rsc@golang.org> |
||
|---|---|---|
| api | ||
| doc | ||
| lib/time | ||
| misc | ||
| src | ||
| test | ||
| .gitattributes | ||
| .gitignore | ||
| AUTHORS | ||
| CONTRIBUTING.md | ||
| CONTRIBUTORS | ||
| LICENSE | ||
| PATENTS | ||
| README.md | ||
| favicon.ico | ||
| robots.txt | ||
README.md
The Go Programming Language
Go is an open source programming language that makes it easy to build simple, reliable, and efficient software.
For documentation about how to install and use Go, visit https://golang.org/ or load doc/install-source.html in your web browser.
Our canonical Git repository is located at https://go.googlesource.com/go. There is a mirror of the repository at https://github.com/golang/go.
Go is the work of hundreds of contributors. We appreciate your help!
To contribute, please read the contribution guidelines: https://golang.org/doc/contribute.html
Note that we do not accept pull requests and that we use the issue tracker for bug reports and proposals only. Please ask questions on https://forum.golangbridge.org or https://groups.google.com/forum/#!forum/golang-nuts.
Unless otherwise noted, the Go source files are distributed under the BSD-style license found in the LICENSE file.
--
Binary Distribution Notes
If you have just untarred a binary Go distribution, you need to set the environment variable $GOROOT to the full path of the go directory (the one containing this file). You can omit the variable if you unpack it into /usr/local/go, or if you rebuild from sources by running all.bash (see doc/install-source.html). You should also add the Go binary directory $GOROOT/bin to your shell's path.
For example, if you extracted the tar file into $HOME/go, you might put the following in your .profile:
export GOROOT=$HOME/go
export PATH=$PATH:$GOROOT/bin
See https://golang.org/doc/install or doc/install.html for more details.
