aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/signal_windows.go
diff options
context:
space:
mode:
authorAlex Brainman <alex.brainman@gmail.com>2015-04-09 15:13:48 +1000
committerAlex Brainman <alex.brainman@gmail.com>2015-04-09 09:55:38 +0000
commit6e774faed773afa1ff7345e2c2d4367e9510388d (patch)
tree6a533770d97b32a5acbb642aeb77b3889d4926b5 /src/runtime/signal_windows.go
parenta513088396d28794c2b2e1bb5e5f2a827e922b4a (diff)
downloadgo-6e774faed773afa1ff7345e2c2d4367e9510388d.tar.gz
go-6e774faed773afa1ff7345e2c2d4367e9510388d.zip
runtime: make windows exception handler code arch independent
Mainly it is simple copy. But I had to change amd64 lastcontinuehandler return value from uint32 to int32. I don't remember how it happened to be uint32, but new int32 is matching better with Windows documentation (LONG). I don't think it matters one way or the others. Change-Id: I6935224a2470ad6301e27590f2baa86c13bbe8d5 Reviewed-on: https://go-review.googlesource.com/8686 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
Diffstat (limited to 'src/runtime/signal_windows.go')
-rw-r--r--src/runtime/signal_windows.go117
1 files changed, 117 insertions, 0 deletions
diff --git a/src/runtime/signal_windows.go b/src/runtime/signal_windows.go
new file mode 100644
index 0000000000..ab8fe206c7
--- /dev/null
+++ b/src/runtime/signal_windows.go
@@ -0,0 +1,117 @@
+// Copyright 2011 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.
+
+package runtime
+
+import (
+ "unsafe"
+)
+
+func isgoexception(info *exceptionrecord, r *context) bool {
+ // Only handle exception if executing instructions in Go binary
+ // (not Windows library code).
+ if r.ip() < themoduledata.text || themoduledata.etext < r.ip() {
+ return false
+ }
+
+ if issigpanic(info.exceptioncode) == 0 {
+ return false
+ }
+
+ return true
+}
+
+// Called by sigtramp from Windows VEH handler.
+// Return value signals whether the exception has been handled (EXCEPTION_CONTINUE_EXECUTION)
+// or should be made available to other handlers in the chain (EXCEPTION_CONTINUE_SEARCH).
+
+func exceptionhandler(info *exceptionrecord, r *context, gp *g) int32 {
+ if !isgoexception(info, r) {
+ return _EXCEPTION_CONTINUE_SEARCH
+ }
+
+ // Make it look like a call to the signal func.
+ // Have to pass arguments out of band since
+ // augmenting the stack frame would break
+ // the unwinding code.
+ gp.sig = info.exceptioncode
+ gp.sigcode0 = uintptr(info.exceptioninformation[0])
+ gp.sigcode1 = uintptr(info.exceptioninformation[1])
+ gp.sigpc = r.ip()
+
+ // Only push runtime·sigpanic if r.ip() != 0.
+ // If r.ip() == 0, probably panicked because of a
+ // call to a nil func. Not pushing that onto sp will
+ // make the trace look like a call to runtime·sigpanic instead.
+ // (Otherwise the trace will end at runtime·sigpanic and we
+ // won't get to see who faulted.)
+ if r.ip() != 0 {
+ sp := unsafe.Pointer(r.sp())
+ sp = add(sp, ^uintptr(unsafe.Sizeof(uintptr(0))-1)) // sp--
+ *((*uintptr)(sp)) = r.ip()
+ r.setsp(uintptr(sp))
+ }
+ r.setip(funcPC(sigpanic))
+ return _EXCEPTION_CONTINUE_EXECUTION
+}
+
+// It seems Windows searches ContinueHandler's list even
+// if ExceptionHandler returns EXCEPTION_CONTINUE_EXECUTION.
+// firstcontinuehandler will stop that search,
+// if exceptionhandler did the same earlier.
+func firstcontinuehandler(info *exceptionrecord, r *context, gp *g) int32 {
+ if !isgoexception(info, r) {
+ return _EXCEPTION_CONTINUE_SEARCH
+ }
+ return _EXCEPTION_CONTINUE_EXECUTION
+}
+
+var testingWER bool
+
+// lastcontinuehandler is reached, because runtime cannot handle
+// current exception. lastcontinuehandler will print crash info and exit.
+func lastcontinuehandler(info *exceptionrecord, r *context, gp *g) int32 {
+ if testingWER {
+ return _EXCEPTION_CONTINUE_SEARCH
+ }
+
+ _g_ := getg()
+
+ if panicking != 0 { // traceback already printed
+ exit(2)
+ }
+ panicking = 1
+
+ print("Exception ", hex(info.exceptioncode), " ", hex(info.exceptioninformation[0]), " ", hex(info.exceptioninformation[1]), " ", hex(r.ip()), "\n")
+
+ print("PC=", hex(r.ip()), "\n")
+ if _g_.m.lockedg != nil && _g_.m.ncgo > 0 && gp == _g_.m.g0 {
+ print("signal arrived during cgo execution\n")
+ gp = _g_.m.lockedg
+ }
+ print("\n")
+
+ var docrash bool
+ if gotraceback(&docrash) > 0 {
+ tracebacktrap(r.ip(), r.sp(), 0, gp)
+ tracebackothers(gp)
+ dumpregs(r)
+ }
+
+ if docrash {
+ crash()
+ }
+
+ exit(2)
+ return 0 // not reached
+}
+
+func sigenable(sig uint32) {
+}
+
+func sigdisable(sig uint32) {
+}
+
+func sigignore(sig uint32) {
+}