mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
runtime: handle windows exceptions, even in cgo programs
Fixes #3543. R=golang-dev, kardianos, rsc CC=golang-dev, hectorchu, vcc.163 https://golang.org/cl/6245063
This commit is contained in:
parent
034fa90dc1
commit
afe0e97aa6
10 changed files with 159 additions and 17 deletions
100
src/pkg/runtime/crash_test.go
Normal file
100
src/pkg/runtime/crash_test.go
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package runtime_test
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
type crashTest struct {
|
||||
Cgo bool
|
||||
}
|
||||
|
||||
// This test is a separate program, because it is testing
|
||||
// both main (m0) and non-main threads (m).
|
||||
|
||||
func testCrashHandler(t *testing.T, ct *crashTest) {
|
||||
st := template.Must(template.New("crashSource").Parse(crashSource))
|
||||
|
||||
dir, err := ioutil.TempDir("", "go-build")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create temp directory: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
src := filepath.Join(dir, "main.go")
|
||||
f, err := os.Create(src)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create %v: %v", src, err)
|
||||
}
|
||||
err = st.Execute(f, ct)
|
||||
if err != nil {
|
||||
f.Close()
|
||||
t.Fatalf("failed to execute template: %v", err)
|
||||
}
|
||||
f.Close()
|
||||
|
||||
got, err := exec.Command("go", "run", src).CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("program exited with error: %v\n%v", err, string(got))
|
||||
}
|
||||
want := "main: recovered done\nnew-thread: recovered done\nsecond-new-thread: recovered done\nmain-again: recovered done\n"
|
||||
if string(got) != string(want) {
|
||||
t.Fatalf("expected %q, but got %q", string(want), string(got))
|
||||
}
|
||||
}
|
||||
|
||||
func TestCrashHandler(t *testing.T) {
|
||||
testCrashHandler(t, &crashTest{Cgo: false})
|
||||
}
|
||||
|
||||
const crashSource = `
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
{{if .Cgo}}
|
||||
import "C"
|
||||
{{end}}
|
||||
|
||||
func test(name string) {
|
||||
defer func() {
|
||||
if x := recover(); x != nil {
|
||||
fmt.Printf(" recovered")
|
||||
}
|
||||
fmt.Printf(" done\n")
|
||||
}()
|
||||
fmt.Printf("%s:", name)
|
||||
var s *string
|
||||
_ = *s
|
||||
fmt.Print("SHOULD NOT BE HERE")
|
||||
}
|
||||
|
||||
func testInNewThread(name string) {
|
||||
c := make(chan bool)
|
||||
go func() {
|
||||
runtime.LockOSThread()
|
||||
test(name)
|
||||
c <- true
|
||||
}()
|
||||
<-c
|
||||
}
|
||||
|
||||
func main() {
|
||||
runtime.LockOSThread()
|
||||
test("main")
|
||||
testInNewThread("new-thread")
|
||||
testInNewThread("second-new-thread")
|
||||
test("main-again")
|
||||
}
|
||||
`
|
||||
Loading…
Add table
Add a link
Reference in a new issue