github.com/geraldss/go/src@v0.0.0-20210511222824-ac7d0ebfc235/runtime/testdata/testprog/deadlock.go (about) 1 // Copyright 2015 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 package main 6 7 import ( 8 "fmt" 9 "runtime" 10 "runtime/debug" 11 "time" 12 ) 13 14 func init() { 15 registerInit("InitDeadlock", InitDeadlock) 16 registerInit("NoHelperGoroutines", NoHelperGoroutines) 17 18 register("SimpleDeadlock", SimpleDeadlock) 19 register("LockedDeadlock", LockedDeadlock) 20 register("LockedDeadlock2", LockedDeadlock2) 21 register("GoexitDeadlock", GoexitDeadlock) 22 register("StackOverflow", StackOverflow) 23 register("ThreadExhaustion", ThreadExhaustion) 24 register("RecursivePanic", RecursivePanic) 25 register("RecursivePanic2", RecursivePanic2) 26 register("RecursivePanic3", RecursivePanic3) 27 register("RecursivePanic4", RecursivePanic4) 28 register("GoexitExit", GoexitExit) 29 register("GoNil", GoNil) 30 register("MainGoroutineID", MainGoroutineID) 31 register("Breakpoint", Breakpoint) 32 register("GoexitInPanic", GoexitInPanic) 33 register("PanicAfterGoexit", PanicAfterGoexit) 34 register("RecoveredPanicAfterGoexit", RecoveredPanicAfterGoexit) 35 register("RecoverBeforePanicAfterGoexit", RecoverBeforePanicAfterGoexit) 36 register("RecoverBeforePanicAfterGoexit2", RecoverBeforePanicAfterGoexit2) 37 register("PanicTraceback", PanicTraceback) 38 register("GoschedInPanic", GoschedInPanic) 39 register("SyscallInPanic", SyscallInPanic) 40 register("PanicLoop", PanicLoop) 41 } 42 43 func SimpleDeadlock() { 44 select {} 45 panic("not reached") 46 } 47 48 func InitDeadlock() { 49 select {} 50 panic("not reached") 51 } 52 53 func LockedDeadlock() { 54 runtime.LockOSThread() 55 select {} 56 } 57 58 func LockedDeadlock2() { 59 go func() { 60 runtime.LockOSThread() 61 select {} 62 }() 63 time.Sleep(time.Millisecond) 64 select {} 65 } 66 67 func GoexitDeadlock() { 68 F := func() { 69 for i := 0; i < 10; i++ { 70 } 71 } 72 73 go F() 74 go F() 75 runtime.Goexit() 76 } 77 78 func StackOverflow() { 79 var f func() byte 80 f = func() byte { 81 var buf [64 << 10]byte 82 return buf[0] + f() 83 } 84 debug.SetMaxStack(1474560) 85 f() 86 } 87 88 func ThreadExhaustion() { 89 debug.SetMaxThreads(10) 90 c := make(chan int) 91 for i := 0; i < 100; i++ { 92 go func() { 93 runtime.LockOSThread() 94 c <- 0 95 select {} 96 }() 97 <-c 98 } 99 } 100 101 func RecursivePanic() { 102 func() { 103 defer func() { 104 fmt.Println(recover()) 105 }() 106 var x [8192]byte 107 func(x [8192]byte) { 108 defer func() { 109 if err := recover(); err != nil { 110 panic("wrap: " + err.(string)) 111 } 112 }() 113 panic("bad") 114 }(x) 115 }() 116 panic("again") 117 } 118 119 // Same as RecursivePanic, but do the first recover and the second panic in 120 // separate defers, and make sure they are executed in the correct order. 121 func RecursivePanic2() { 122 func() { 123 defer func() { 124 fmt.Println(recover()) 125 }() 126 var x [8192]byte 127 func(x [8192]byte) { 128 defer func() { 129 panic("second panic") 130 }() 131 defer func() { 132 fmt.Println(recover()) 133 }() 134 panic("first panic") 135 }(x) 136 }() 137 panic("third panic") 138 } 139 140 // Make sure that the first panic finished as a panic, even though the second 141 // panic was recovered 142 func RecursivePanic3() { 143 defer func() { 144 defer func() { 145 recover() 146 }() 147 panic("second panic") 148 }() 149 panic("first panic") 150 } 151 152 // Test case where a single defer recovers one panic but starts another panic. If 153 // the second panic is never recovered, then the recovered first panic will still 154 // appear on the panic stack (labeled '[recovered]') and the runtime stack. 155 func RecursivePanic4() { 156 defer func() { 157 recover() 158 panic("second panic") 159 }() 160 panic("first panic") 161 } 162 163 func GoexitExit() { 164 println("t1") 165 go func() { 166 time.Sleep(time.Millisecond) 167 }() 168 i := 0 169 println("t2") 170 runtime.SetFinalizer(&i, func(p *int) {}) 171 println("t3") 172 runtime.GC() 173 println("t4") 174 runtime.Goexit() 175 } 176 177 func GoNil() { 178 defer func() { 179 recover() 180 }() 181 var f func() 182 go f() 183 select {} 184 } 185 186 func MainGoroutineID() { 187 panic("test") 188 } 189 190 func NoHelperGoroutines() { 191 i := 0 192 runtime.SetFinalizer(&i, func(p *int) {}) 193 time.AfterFunc(time.Hour, func() {}) 194 panic("oops") 195 } 196 197 func Breakpoint() { 198 runtime.Breakpoint() 199 } 200 201 func GoexitInPanic() { 202 go func() { 203 defer func() { 204 runtime.Goexit() 205 }() 206 panic("hello") 207 }() 208 runtime.Goexit() 209 } 210 211 type errorThatGosched struct{} 212 213 func (errorThatGosched) Error() string { 214 runtime.Gosched() 215 return "errorThatGosched" 216 } 217 218 func GoschedInPanic() { 219 panic(errorThatGosched{}) 220 } 221 222 type errorThatPrint struct{} 223 224 func (errorThatPrint) Error() string { 225 fmt.Println("1") 226 fmt.Println("2") 227 return "3" 228 } 229 230 func SyscallInPanic() { 231 panic(errorThatPrint{}) 232 } 233 234 func PanicAfterGoexit() { 235 defer func() { 236 panic("hello") 237 }() 238 runtime.Goexit() 239 } 240 241 func RecoveredPanicAfterGoexit() { 242 defer func() { 243 defer func() { 244 r := recover() 245 if r == nil { 246 panic("bad recover") 247 } 248 }() 249 panic("hello") 250 }() 251 runtime.Goexit() 252 } 253 254 func RecoverBeforePanicAfterGoexit() { 255 // 1. defer a function that recovers 256 // 2. defer a function that panics 257 // 3. call goexit 258 // Goexit runs the #2 defer. Its panic 259 // is caught by the #1 defer. For Goexit, we explicitly 260 // resume execution in the Goexit loop, instead of resuming 261 // execution in the caller (which would make the Goexit disappear!) 262 defer func() { 263 r := recover() 264 if r == nil { 265 panic("bad recover") 266 } 267 }() 268 defer func() { 269 panic("hello") 270 }() 271 runtime.Goexit() 272 } 273 274 func RecoverBeforePanicAfterGoexit2() { 275 for i := 0; i < 2; i++ { 276 defer func() { 277 }() 278 } 279 // 1. defer a function that recovers 280 // 2. defer a function that panics 281 // 3. call goexit 282 // Goexit runs the #2 defer. Its panic 283 // is caught by the #1 defer. For Goexit, we explicitly 284 // resume execution in the Goexit loop, instead of resuming 285 // execution in the caller (which would make the Goexit disappear!) 286 defer func() { 287 r := recover() 288 if r == nil { 289 panic("bad recover") 290 } 291 }() 292 defer func() { 293 panic("hello") 294 }() 295 runtime.Goexit() 296 } 297 298 func PanicTraceback() { 299 pt1() 300 } 301 302 func pt1() { 303 defer func() { 304 panic("panic pt1") 305 }() 306 pt2() 307 } 308 309 func pt2() { 310 defer func() { 311 panic("panic pt2") 312 }() 313 panic("hello") 314 } 315 316 type panicError struct{} 317 318 func (*panicError) Error() string { 319 panic("double error") 320 } 321 322 func PanicLoop() { 323 panic(&panicError{}) 324 }