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