• 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
api Loading commit data...
doc Loading commit data...
include Loading commit data...
lib Loading commit data...
misc Loading commit data...
src Loading commit data...
test Loading commit data...
.hgignore Loading commit data...
.hgtags Loading commit data...
AUTHORS Loading commit data...
CONTRIBUTORS Loading commit data...
LICENSE Loading commit data...
PATENTS Loading commit data...
README Loading commit data...
favicon.ico Loading commit data...
robots.txt Loading commit data...