1
0
mirror of https://github.com/golang/go synced 2024-11-19 16:44:43 -07:00

runtime: move all exception related code into signal_windows.go

Change-Id: I9654a5c85bd9b3ae9c7a9eddaef1ec752f42bd1b
Reviewed-on: https://go-review.googlesource.com/8840
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
Alex Brainman 2015-04-13 12:02:44 +10:00
parent e6092d64a7
commit d1af6bed84
3 changed files with 106 additions and 126 deletions

View File

@ -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 //go:nosplit
func getLoadLibrary() uintptr { func getLoadLibrary() uintptr {
return uintptr(unsafe.Pointer(_LoadLibraryW)) return uintptr(unsafe.Pointer(_LoadLibraryW))
@ -144,24 +138,15 @@ const (
currentThread = ^uintptr(1) // -2 = current thread 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) { func getVersion() (major, minor byte) {
v := uint32(stdcall0(_GetVersion)) v := uint32(stdcall0(_GetVersion))
low := uint16(v) low := uint16(v)
return byte(low), byte(low >> 8) return byte(low), byte(low >> 8)
} }
// in sys_windows_386.s and sys_windows_amd64.s
func externalthreadhandler()
func osinit() { func osinit() {
asmstdcallAddr = unsafe.Pointer(funcPC(asmstdcall)) asmstdcallAddr = unsafe.Pointer(funcPC(asmstdcall))
@ -173,21 +158,7 @@ func osinit() {
externalthreadhandlerp = funcPC(externalthreadhandler) externalthreadhandlerp = funcPC(externalthreadhandler)
major, _ := getVersion() initExceptionHandler()
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))
}
stdcall2(_SetConsoleCtrlHandler, funcPC(ctrlhandler), 1) stdcall2(_SetConsoleCtrlHandler, funcPC(ctrlhandler), 1)
@ -482,37 +453,6 @@ func usleep(us uint32) {
usleep1(10 * us) 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 { func ctrlhandler1(_type uint32) uint32 {
var s uint32 var s uint32
@ -604,35 +544,3 @@ func resetcpuprofiler(hz int32) {
func memlimit() uintptr { func memlimit() uintptr {
return 0 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.
}

View File

@ -13,33 +13,6 @@ func os_sigpipe() {
throw("too many writes on closed pipe") 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. // Stubs so tests can link correctly. These should never be called.
func open(name *byte, mode, perm int32) int32 { func open(name *byte, mode, perm int32) int32 {
throw("unimplemented") throw("unimplemented")

View File

@ -8,6 +8,40 @@ import (
"unsafe" "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 { func isgoexception(info *exceptionrecord, r *context) bool {
// Only handle exception if executing instructions in Go binary // Only handle exception if executing instructions in Go binary
// (not Windows library code). // (not Windows library code).
@ -16,17 +50,26 @@ func isgoexception(info *exceptionrecord, r *context) bool {
return false return false
} }
if issigpanic(info.exceptioncode) == 0 { // Go will only handle some exceptions.
switch info.exceptioncode {
default:
return false 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 return true
} }
// Called by sigtramp from Windows VEH handler. // Called by sigtramp from Windows VEH handler.
// Return value signals whether the exception has been handled (EXCEPTION_CONTINUE_EXECUTION) // 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). // or should be made available to other handlers in the chain (EXCEPTION_CONTINUE_SEARCH).
func exceptionhandler(info *exceptionrecord, r *context, gp *g) int32 { func exceptionhandler(info *exceptionrecord, r *context, gp *g) int32 {
if !isgoexception(info, r) { if !isgoexception(info, r) {
return _EXCEPTION_CONTINUE_SEARCH return _EXCEPTION_CONTINUE_SEARCH
@ -108,6 +151,51 @@ func lastcontinuehandler(info *exceptionrecord, r *context, gp *g) int32 {
return 0 // not reached 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) { func sigenable(sig uint32) {
} }
@ -116,3 +204,14 @@ func sigdisable(sig uint32) {
func sigignore(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.
}