1
2
3
4
5 package main
6
7 import (
8 "flag"
9 "fmt"
10 "os"
11 "runtime"
12 "runtime/pprof"
13 )
14
15 var finalizerDeadlockMode = flag.String("finalizer-deadlock-mode", "panic", "Trigger mode of FinalizerDeadlock")
16
17 func init() {
18 register("FinalizerDeadlock", FinalizerDeadlock)
19 }
20
21 func FinalizerDeadlock() {
22 flag.Parse()
23
24 started := make(chan struct{})
25 b := new([16]byte)
26 runtime.SetFinalizer(b, func(*[16]byte) {
27 started <- struct{}{}
28 select {}
29 })
30 b = nil
31
32 runtime.GC()
33
34 <-started
35
36
37
38
39 mode := os.Getenv("GO_TEST_FINALIZER_DEADLOCK")
40 switch mode {
41 case "panic":
42 panic("panic")
43 case "stack":
44 buf := make([]byte, 4096)
45 for {
46 n := runtime.Stack(buf, true)
47 if n >= len(buf) {
48 buf = make([]byte, 2*len(buf))
49 continue
50 }
51 buf = buf[:n]
52 break
53 }
54 fmt.Printf("%s\n", string(buf))
55 case "pprof_proto":
56 if err := pprof.Lookup("goroutine").WriteTo(os.Stdout, 0); err != nil {
57 fmt.Fprintf(os.Stderr, "Error writing profile: %v\n", err)
58 os.Exit(1)
59 }
60 case "pprof_debug1":
61 if err := pprof.Lookup("goroutine").WriteTo(os.Stdout, 1); err != nil {
62 fmt.Fprintf(os.Stderr, "Error writing profile: %v\n", err)
63 os.Exit(1)
64 }
65 case "pprof_debug2":
66 if err := pprof.Lookup("goroutine").WriteTo(os.Stdout, 2); err != nil {
67 fmt.Fprintf(os.Stderr, "Error writing profile: %v\n", err)
68 os.Exit(1)
69 }
70 default:
71 fmt.Fprintf(os.Stderr, "Unknown mode %q. GO_TEST_FINALIZER_DEADLOCK must be one of panic, stack, pprof_proto, pprof_debug1, pprof_debug2\n", mode)
72 os.Exit(1)
73 }
74 }
75
View as plain text