runtime: crash earlier on windows for runtime.abort

The isAbort check was wrong for non-x86 systems.
That was causing the exception chain to be passed back to Windows.
That was causing some other kind of fault - not sure what.
That was leading back to lastcontinuehandler to print a larger
stack trace, and then the throwing = 1 print added runtime.abort,
which made TestAbort pass even though it wasn't really working.

Recognize abort properly and handle it as Go, not as something
for Windows to try to handle.

Keep the throwing = 1 print, because more detail on throw is
always better.

This CL is part of a stack adding windows/arm64
support (#36439), intended to land in the Go 1.17 cycle.
This CL is, however, not windows/arm64-specific.
It is cleanup meant to make the port (and future ports) easier.

Change-Id: If614f4ab2884bd90410d29e28311bf969ceeac09
Reviewed-on: https://go-review.googlesource.com/c/go/+/288810
Trust: Russ Cox <rsc@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
Russ Cox 2021-01-27 11:15:33 -05:00
parent a1e9148e3d
commit 38672d3dcf

View File

@ -43,13 +43,17 @@ func initExceptionHandler() {
//
//go:nosplit
func isAbort(r *context) bool {
// In the case of an abort, the exception IP is one byte after
// the INT3 (this differs from UNIX OSes).
return isAbortPC(r.ip() - 1)
pc := r.ip()
if GOARCH == "386" || GOARCH == "amd64" {
// In the case of an abort, the exception IP is one byte after
// the INT3 (this differs from UNIX OSes).
pc--
}
return isAbortPC(pc)
}
// isgoexception reports whether this exception should be translated
// into a Go panic.
// into a Go panic or throw.
//
// It is nosplit to avoid growing the stack in case we're aborting
// because of a stack overflow.
@ -63,11 +67,6 @@ func isgoexception(info *exceptionrecord, r *context) bool {
return false
}
if isAbort(r) {
// Never turn abort into a panic.
return false
}
// Go will only handle some exceptions.
switch info.exceptioncode {
default:
@ -99,14 +98,16 @@ func exceptionhandler(info *exceptionrecord, r *context, gp *g) int32 {
return _EXCEPTION_CONTINUE_SEARCH
}
// After this point, it is safe to grow the stack.
if gp.throwsplit {
// We can't safely sigpanic because it may grow the
// stack. Let it fall through.
return _EXCEPTION_CONTINUE_SEARCH
if gp.throwsplit || isAbort(r) {
// We can't safely sigpanic because it may grow the stack.
// Or this is a call to abort.
// Don't go through any more of the Windows handler chain.
// Crash now.
winthrow(info, r, gp)
}
// After this point, it is safe to grow the stack.
// Make it look like a call to the signal func.
// Have to pass arguments out of band since
// augmenting the stack frame would break
@ -181,6 +182,12 @@ func lastcontinuehandler(info *exceptionrecord, r *context, gp *g) int32 {
return _EXCEPTION_CONTINUE_SEARCH
}
winthrow(info, r, gp)
return 0 // not reached
}
//go:nosplit
func winthrow(info *exceptionrecord, r *context, gp *g) {
_g_ := getg()
if panicking != 0 { // traceback already printed
@ -206,11 +213,8 @@ func lastcontinuehandler(info *exceptionrecord, r *context, gp *g) int32 {
}
print("\n")
// TODO(jordanrh1): This may be needed for 386/AMD64 as well.
if GOARCH == "arm" {
_g_.m.throwing = 1
_g_.m.caughtsig.set(gp)
}
_g_.m.throwing = 1
_g_.m.caughtsig.set(gp)
level, _, docrash := gotraceback()
if level > 0 {
@ -224,7 +228,6 @@ func lastcontinuehandler(info *exceptionrecord, r *context, gp *g) int32 {
}
exit(2)
return 0 // not reached
}
func sigpanic() {