• Russ Cox's avatar
    runtime: handle Go calls C calls Go panic correctly on windows/386 · 1249d3a5
    Russ Cox authored
    32-bit Windows uses "structured exception handling" (SEH) to
    handle hardware faults: that there is a per-thread linked list
    of fault handlers maintained in user space instead of
    something like Unix's signal handlers. The structures in the
    linked list are required to live on the OS stack, and the
    usual discipline is that the function that pushes a record
    (allocated from the current stack frame) onto the list pops
    that record before returning. Not to pop the entry before
    returning creates a dangling pointer error: the list head
    points to a stack frame that no longer exists.
    
    Go pushes an SEH record in the top frame of every OS thread,
    and that record suffices for all Go execution on that thread,
    at least until cgo gets involved.
    
    If we call into C using cgo, that called C code may push its
    own SEH records, but by the convention it must pop them before
    returning back to the Go code. We assume it does, and that's
    fine.
    
    If the C code calls back into Go, we want the Go SEH handler
    to become active again, not whatever C has set up. So
    runtime.callbackasm1, which handles a call from C back into
    Go, pushes a new SEH record before calling the Go code and
    pops it when the Go code returns. That's also fine.
    
    It can happen that when Go calls C calls Go like this, the
    inner Go code panics. We allow a defer in the outer Go to
    recover the panic, effectively wiping not only the inner Go
    frames but also the C calls. This sequence was not popping the
    SEH stack up to what it was before the cgo calls, so it was
    creating the dangling pointer warned about above. When
    eventually the m stack was used enough to overwrite the
    dangling SEH records, the SEH chain was lost, and any future
    panic would not end up in Go's handler.
    
    The bug in TestCallbackPanic and friends was thus creating a
    situation where TestSetPanicOnFault - which causes a hardware
    fault - would not find the Go fault handler and instead crash
    the binary.
    
    Add checks to TestCallbackPanicLocked to diagnose the mistake
    in that test instead of leaving a bad state for another test
    case to stumble over.
    
    Fix bug by restoring SEH chain during deferred "endcgo"
    cleanup.
    
    This bug is likely present in Go 1.2.1, but since it depends
    on Go calling C calling Go, with the inner Go panicking and
    the outer Go recovering the panic, it seems not important
    enough to bother fixing before Go 1.3. Certainly no one has
    complained.
    
    Fixes #7470.
    
    LGTM=alex.brainman
    R=golang-codereviews, alex.brainman
    CC=golang-codereviews, iant, khr
    https://golang.org/cl/71440043
    1249d3a5
Name
Last commit
Last update
..
archive Loading commit data...
bufio Loading commit data...
builtin Loading commit data...
bytes Loading commit data...
compress Loading commit data...
container Loading commit data...
crypto Loading commit data...
database/sql Loading commit data...
debug Loading commit data...
encoding Loading commit data...
errors Loading commit data...
expvar Loading commit data...
flag Loading commit data...
fmt Loading commit data...
go Loading commit data...
hash Loading commit data...
html Loading commit data...
image Loading commit data...
index/suffixarray Loading commit data...
io Loading commit data...
log Loading commit data...
math Loading commit data...
mime Loading commit data...
net Loading commit data...
os Loading commit data...
path Loading commit data...
reflect Loading commit data...
regexp Loading commit data...
runtime Loading commit data...
sort Loading commit data...
strconv Loading commit data...
strings Loading commit data...
sync Loading commit data...
syscall Loading commit data...
testing Loading commit data...
text Loading commit data...
time Loading commit data...
unicode Loading commit data...
unsafe Loading commit data...