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  }