Source file src/runtime/testdata/testprog/deadlock.go

     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  }
   364  

View as plain text