1// Copyright 2023 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// Tests stack symbolization. 6 7//go:build ignore 8 9package main 10 11import ( 12 "log" 13 "net" 14 "os" 15 "runtime" 16 "runtime/trace" 17 "sync" 18 "time" 19) 20 21func main() { 22 if err := trace.Start(os.Stdout); err != nil { 23 log.Fatalf("failed to start tracing: %v", err) 24 } 25 defer trace.Stop() // in case of early return 26 27 // Now we will do a bunch of things for which we verify stacks later. 28 // It is impossible to ensure that a goroutine has actually blocked 29 // on a channel, in a select or otherwise. So we kick off goroutines 30 // that need to block first in the hope that while we are executing 31 // the rest of the test, they will block. 32 go func() { // func1 33 select {} 34 }() 35 go func() { // func2 36 var c chan int 37 c <- 0 38 }() 39 go func() { // func3 40 var c chan int 41 <-c 42 }() 43 done1 := make(chan bool) 44 go func() { // func4 45 <-done1 46 }() 47 done2 := make(chan bool) 48 go func() { // func5 49 done2 <- true 50 }() 51 c1 := make(chan int) 52 c2 := make(chan int) 53 go func() { // func6 54 select { 55 case <-c1: 56 case <-c2: 57 } 58 }() 59 var mu sync.Mutex 60 mu.Lock() 61 go func() { // func7 62 mu.Lock() 63 mu.Unlock() 64 }() 65 var wg sync.WaitGroup 66 wg.Add(1) 67 go func() { // func8 68 wg.Wait() 69 }() 70 cv := sync.NewCond(&sync.Mutex{}) 71 go func() { // func9 72 cv.L.Lock() 73 cv.Wait() 74 cv.L.Unlock() 75 }() 76 ln, err := net.Listen("tcp", "127.0.0.1:0") 77 if err != nil { 78 log.Fatalf("failed to listen: %v", err) 79 } 80 go func() { // func10 81 c, err := ln.Accept() 82 if err != nil { 83 log.Printf("failed to accept: %v", err) 84 return 85 } 86 c.Close() 87 }() 88 rp, wp, err := os.Pipe() 89 if err != nil { 90 log.Fatalf("failed to create a pipe: %v", err) 91 } 92 defer rp.Close() 93 defer wp.Close() 94 pipeReadDone := make(chan bool) 95 go func() { // func11 96 var data [1]byte 97 rp.Read(data[:]) 98 pipeReadDone <- true 99 }() 100 101 time.Sleep(100 * time.Millisecond) 102 runtime.GC() 103 runtime.Gosched() 104 time.Sleep(100 * time.Millisecond) // the last chance for the goroutines above to block 105 done1 <- true 106 <-done2 107 select { 108 case c1 <- 0: 109 case c2 <- 0: 110 } 111 mu.Unlock() 112 wg.Done() 113 cv.Signal() 114 c, err := net.Dial("tcp", ln.Addr().String()) 115 if err != nil { 116 log.Fatalf("failed to dial: %v", err) 117 } 118 c.Close() 119 var data [1]byte 120 wp.Write(data[:]) 121 <-pipeReadDone 122 123 oldGoMaxProcs := runtime.GOMAXPROCS(0) 124 runtime.GOMAXPROCS(oldGoMaxProcs + 1) 125 126 trace.Stop() 127 128 runtime.GOMAXPROCS(oldGoMaxProcs) 129} 130