Commit d1af6bed authored by Alex Brainman's avatar Alex Brainman

runtime: move all exception related code into signal_windows.go

Change-Id: I9654a5c85bd9b3ae9c7a9eddaef1ec752f42bd1b
Reviewed-on: https://go-review.googlesource.com/8840Reviewed-by: 's avatarBrad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent e6092d64
......@@ -117,12 +117,6 @@ func loadOptionalSyscalls() {
}
}
// in sys_windows_386.s and sys_windows_amd64.s
func externalthreadhandler()
func exceptiontramp()
func firstcontinuetramp()
func lastcontinuetramp()
//go:nosplit
func getLoadLibrary() uintptr {
return uintptr(unsafe.Pointer(_LoadLibraryW))
......@@ -144,24 +138,15 @@ const (
currentThread = ^uintptr(1) // -2 = current thread
)
func disableWER() {
// do not display Windows Error Reporting dialogue
const (
SEM_FAILCRITICALERRORS = 0x0001
SEM_NOGPFAULTERRORBOX = 0x0002
SEM_NOALIGNMENTFAULTEXCEPT = 0x0004
SEM_NOOPENFILEERRORBOX = 0x8000
)
errormode := uint32(stdcall1(_SetErrorMode, SEM_NOGPFAULTERRORBOX))
stdcall1(_SetErrorMode, uintptr(errormode)|SEM_FAILCRITICALERRORS|SEM_NOGPFAULTERRORBOX|SEM_NOOPENFILEERRORBOX)
}
func getVersion() (major, minor byte) {
v := uint32(stdcall0(_GetVersion))
low := uint16(v)
return byte(low), byte(low >> 8)
}
// in sys_windows_386.s and sys_windows_amd64.s
func externalthreadhandler()
func osinit() {
asmstdcallAddr = unsafe.Pointer(funcPC(asmstdcall))
......@@ -173,21 +158,7 @@ func osinit() {
externalthreadhandlerp = funcPC(externalthreadhandler)
major, _ := getVersion()
stdcall2(_AddVectoredExceptionHandler, 1, funcPC(exceptiontramp))
if _AddVectoredContinueHandler == nil || unsafe.Sizeof(&_AddVectoredContinueHandler) == 4 || major < 6 {
// use SetUnhandledExceptionFilter for windows-386 or
// if VectoredContinueHandler is unavailable or
// if running windows-amd64 v5. V5 appears to fail to
// call the continue handlers if windows error reporting dialog
// is disabled.
// note: SetUnhandledExceptionFilter handler won't be called, if debugging.
stdcall1(_SetUnhandledExceptionFilter, funcPC(lastcontinuetramp))
} else {
stdcall2(_AddVectoredContinueHandler, 1, funcPC(firstcontinuetramp))
stdcall2(_AddVectoredContinueHandler, 0, funcPC(lastcontinuetramp))
}
initExceptionHandler()
stdcall2(_SetConsoleCtrlHandler, funcPC(ctrlhandler), 1)
......@@ -482,37 +453,6 @@ func usleep(us uint32) {
usleep1(10 * us)
}
func issigpanic(code uint32) uint32 {
switch code {
default:
return 0
case _EXCEPTION_ACCESS_VIOLATION:
case _EXCEPTION_INT_DIVIDE_BY_ZERO:
case _EXCEPTION_INT_OVERFLOW:
case _EXCEPTION_FLT_DENORMAL_OPERAND:
case _EXCEPTION_FLT_DIVIDE_BY_ZERO:
case _EXCEPTION_FLT_INEXACT_RESULT:
case _EXCEPTION_FLT_OVERFLOW:
case _EXCEPTION_FLT_UNDERFLOW:
case _EXCEPTION_BREAKPOINT:
}
return 1
}
func initsig() {
/*
// TODO(brainman): I don't think we need that bit of code
// following line keeps these functions alive at link stage
// if there's a better way please write it here
void *e = runtime·exceptiontramp;
void *f = runtime·firstcontinuetramp;
void *l = runtime·lastcontinuetramp;
USED(e);
USED(f);
USED(l);
*/
}
func ctrlhandler1(_type uint32) uint32 {
var s uint32
......@@ -604,35 +544,3 @@ func resetcpuprofiler(hz int32) {
func memlimit() uintptr {
return 0
}
var (
badsignalmsg [100]byte
badsignallen int32
)
func setBadSignalMsg() {
const msg = "runtime: signal received on thread not created by Go.\n"
for i, c := range msg {
badsignalmsg[i] = byte(c)
badsignallen++
}
}
const (
_SIGPROF = 0 // dummy value for badsignal
_SIGQUIT = 0 // dummy value for sighandler
)
func raiseproc(sig int32) {
}
func crash() {
// TODO: This routine should do whatever is needed
// to make the Windows program abort/crash as it
// would if Go was not intercepting signals.
// On Unix the routine would remove the custom signal
// handler and then raise a signal (like SIGABRT).
// Something like that should happen here.
// It's okay to leave this empty for now: if crash returns
// the ordinary exit-after-panic happens.
}
......@@ -13,33 +13,6 @@ func os_sigpipe() {
throw("too many writes on closed pipe")
}
func sigpanic() {
g := getg()
if !canpanic(g) {
throw("unexpected signal during runtime execution")
}
switch uint32(g.sig) {
case _EXCEPTION_ACCESS_VIOLATION:
if g.sigcode1 < 0x1000 || g.paniconfault {
panicmem()
}
print("unexpected fault address ", hex(g.sigcode1), "\n")
throw("fault")
case _EXCEPTION_INT_DIVIDE_BY_ZERO:
panicdivide()
case _EXCEPTION_INT_OVERFLOW:
panicoverflow()
case _EXCEPTION_FLT_DENORMAL_OPERAND,
_EXCEPTION_FLT_DIVIDE_BY_ZERO,
_EXCEPTION_FLT_INEXACT_RESULT,
_EXCEPTION_FLT_OVERFLOW,
_EXCEPTION_FLT_UNDERFLOW:
panicfloat()
}
throw("fault")
}
// Stubs so tests can link correctly. These should never be called.
func open(name *byte, mode, perm int32) int32 {
throw("unimplemented")
......
......@@ -8,6 +8,40 @@ import (
"unsafe"
)
func disableWER() {
// do not display Windows Error Reporting dialogue
const (
SEM_FAILCRITICALERRORS = 0x0001
SEM_NOGPFAULTERRORBOX = 0x0002
SEM_NOALIGNMENTFAULTEXCEPT = 0x0004
SEM_NOOPENFILEERRORBOX = 0x8000
)
errormode := uint32(stdcall1(_SetErrorMode, SEM_NOGPFAULTERRORBOX))
stdcall1(_SetErrorMode, uintptr(errormode)|SEM_FAILCRITICALERRORS|SEM_NOGPFAULTERRORBOX|SEM_NOOPENFILEERRORBOX)
}
// in sys_windows_386.s and sys_windows_amd64.s
func exceptiontramp()
func firstcontinuetramp()
func lastcontinuetramp()
func initExceptionHandler() {
major, _ := getVersion()
stdcall2(_AddVectoredExceptionHandler, 1, funcPC(exceptiontramp))
if _AddVectoredContinueHandler == nil || unsafe.Sizeof(&_AddVectoredContinueHandler) == 4 || major < 6 {
// use SetUnhandledExceptionFilter for windows-386 or
// if VectoredContinueHandler is unavailable or
// if running windows-amd64 v5. V5 appears to fail to
// call the continue handlers if windows error reporting dialog
// is disabled.
// note: SetUnhandledExceptionFilter handler won't be called, if debugging.
stdcall1(_SetUnhandledExceptionFilter, funcPC(lastcontinuetramp))
} else {
stdcall2(_AddVectoredContinueHandler, 1, funcPC(firstcontinuetramp))
stdcall2(_AddVectoredContinueHandler, 0, funcPC(lastcontinuetramp))
}
}
func isgoexception(info *exceptionrecord, r *context) bool {
// Only handle exception if executing instructions in Go binary
// (not Windows library code).
......@@ -16,17 +50,26 @@ func isgoexception(info *exceptionrecord, r *context) bool {
return false
}
if issigpanic(info.exceptioncode) == 0 {
// Go will only handle some exceptions.
switch info.exceptioncode {
default:
return false
case _EXCEPTION_ACCESS_VIOLATION:
case _EXCEPTION_INT_DIVIDE_BY_ZERO:
case _EXCEPTION_INT_OVERFLOW:
case _EXCEPTION_FLT_DENORMAL_OPERAND:
case _EXCEPTION_FLT_DIVIDE_BY_ZERO:
case _EXCEPTION_FLT_INEXACT_RESULT:
case _EXCEPTION_FLT_OVERFLOW:
case _EXCEPTION_FLT_UNDERFLOW:
case _EXCEPTION_BREAKPOINT:
}
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
......@@ -108,6 +151,51 @@ func lastcontinuehandler(info *exceptionrecord, r *context, gp *g) int32 {
return 0 // not reached
}
func sigpanic() {
g := getg()
if !canpanic(g) {
throw("unexpected signal during runtime execution")
}
switch uint32(g.sig) {
case _EXCEPTION_ACCESS_VIOLATION:
if g.sigcode1 < 0x1000 || g.paniconfault {
panicmem()
}
print("unexpected fault address ", hex(g.sigcode1), "\n")
throw("fault")
case _EXCEPTION_INT_DIVIDE_BY_ZERO:
panicdivide()
case _EXCEPTION_INT_OVERFLOW:
panicoverflow()
case _EXCEPTION_FLT_DENORMAL_OPERAND,
_EXCEPTION_FLT_DIVIDE_BY_ZERO,
_EXCEPTION_FLT_INEXACT_RESULT,
_EXCEPTION_FLT_OVERFLOW,
_EXCEPTION_FLT_UNDERFLOW:
panicfloat()
}
throw("fault")
}
var (
badsignalmsg [100]byte
badsignallen int32
)
func setBadSignalMsg() {
const msg = "runtime: signal received on thread not created by Go.\n"
for i, c := range msg {
badsignalmsg[i] = byte(c)
badsignallen++
}
}
// Following are not implemented.
func initsig() {
}
func sigenable(sig uint32) {
}
......@@ -116,3 +204,14 @@ func sigdisable(sig uint32) {
func sigignore(sig uint32) {
}
func crash() {
// TODO: This routine should do whatever is needed
// to make the Windows program abort/crash as it
// would if Go was not intercepting signals.
// On Unix the routine would remove the custom signal
// handler and then raise a signal (like SIGABRT).
// Something like that should happen here.
// It's okay to leave this empty for now: if crash returns
// the ordinary exit-after-panic happens.
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment