github.com/shijuvar/go@v0.0.0-20141209052335-e8f13700b70c/src/runtime/crash_cgo_test.go (about) 1 // Copyright 2012 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // +build cgo 6 7 package runtime_test 8 9 import ( 10 "runtime" 11 "strings" 12 "testing" 13 ) 14 15 func TestCgoCrashHandler(t *testing.T) { 16 testCrashHandler(t, true) 17 } 18 19 func TestCgoSignalDeadlock(t *testing.T) { 20 if testing.Short() && runtime.GOOS == "windows" { 21 t.Skip("Skipping in short mode") // takes up to 64 seconds 22 } 23 got := executeTest(t, cgoSignalDeadlockSource, nil) 24 want := "OK\n" 25 if got != want { 26 t.Fatalf("expected %q, but got %q", want, got) 27 } 28 } 29 30 func TestCgoTraceback(t *testing.T) { 31 got := executeTest(t, cgoTracebackSource, nil) 32 want := "OK\n" 33 if got != want { 34 t.Fatalf("expected %q, but got %q", want, got) 35 } 36 } 37 38 func TestCgoExternalThreadPanic(t *testing.T) { 39 if runtime.GOOS == "plan9" { 40 t.Skipf("no pthreads on %s", runtime.GOOS) 41 } 42 csrc := cgoExternalThreadPanicC 43 if runtime.GOOS == "windows" { 44 csrc = cgoExternalThreadPanicC_windows 45 } 46 got := executeTest(t, cgoExternalThreadPanicSource, nil, "main.c", csrc) 47 want := "panic: BOOM" 48 if !strings.Contains(got, want) { 49 t.Fatalf("want failure containing %q. output:\n%s\n", want, got) 50 } 51 } 52 53 const cgoSignalDeadlockSource = ` 54 package main 55 56 import "C" 57 58 import ( 59 "fmt" 60 "runtime" 61 "time" 62 ) 63 64 func main() { 65 runtime.GOMAXPROCS(100) 66 ping := make(chan bool) 67 go func() { 68 for i := 0; ; i++ { 69 runtime.Gosched() 70 select { 71 case done := <-ping: 72 if done { 73 ping <- true 74 return 75 } 76 ping <- true 77 default: 78 } 79 func() { 80 defer func() { 81 recover() 82 }() 83 var s *string 84 *s = "" 85 }() 86 } 87 }() 88 time.Sleep(time.Millisecond) 89 for i := 0; i < 64; i++ { 90 go func() { 91 runtime.LockOSThread() 92 select {} 93 }() 94 go func() { 95 runtime.LockOSThread() 96 select {} 97 }() 98 time.Sleep(time.Millisecond) 99 ping <- false 100 select { 101 case <-ping: 102 case <-time.After(time.Second): 103 fmt.Printf("HANG\n") 104 return 105 } 106 } 107 ping <- true 108 select { 109 case <-ping: 110 case <-time.After(time.Second): 111 fmt.Printf("HANG\n") 112 return 113 } 114 fmt.Printf("OK\n") 115 } 116 ` 117 118 const cgoTracebackSource = ` 119 package main 120 121 /* void foo(void) {} */ 122 import "C" 123 124 import ( 125 "fmt" 126 "runtime" 127 ) 128 129 func main() { 130 C.foo() 131 buf := make([]byte, 1) 132 runtime.Stack(buf, true) 133 fmt.Printf("OK\n") 134 } 135 ` 136 137 const cgoExternalThreadPanicSource = ` 138 package main 139 140 // void start(void); 141 import "C" 142 143 func main() { 144 C.start() 145 select {} 146 } 147 148 //export gopanic 149 func gopanic() { 150 panic("BOOM") 151 } 152 ` 153 154 const cgoExternalThreadPanicC = ` 155 #include <stdlib.h> 156 #include <stdio.h> 157 #include <pthread.h> 158 159 void gopanic(void); 160 161 static void* 162 die(void* x) 163 { 164 gopanic(); 165 return 0; 166 } 167 168 void 169 start(void) 170 { 171 pthread_t t; 172 if(pthread_create(&t, 0, die, 0) != 0) 173 printf("pthread_create failed\n"); 174 } 175 ` 176 177 const cgoExternalThreadPanicC_windows = ` 178 #include <stdlib.h> 179 #include <stdio.h> 180 181 void gopanic(void); 182 183 static void* 184 die(void* x) 185 { 186 gopanic(); 187 return 0; 188 } 189 190 void 191 start(void) 192 { 193 if(_beginthreadex(0, 0, die, 0, 0, 0) != 0) 194 printf("_beginthreadex failed\n"); 195 } 196 `