// Copyright 2023 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Tests stack symbolization. //go:build ignore package main import ( "log" "net" "os" "runtime" "runtime/trace" "sync" "time" ) func main() { if err := trace.Start(os.Stdout); err != nil { log.Fatalf("failed to start tracing: %v", err) } defer trace.Stop() // in case of early return // Now we will do a bunch of things for which we verify stacks later. // It is impossible to ensure that a goroutine has actually blocked // on a channel, in a select or otherwise. So we kick off goroutines // that need to block first in the hope that while we are executing // the rest of the test, they will block. go func() { // func1 select {} }() go func() { // func2 var c chan int c <- 0 }() go func() { // func3 var c chan int <-c }() done1 := make(chan bool) go func() { // func4 <-done1 }() done2 := make(chan bool) go func() { // func5 done2 <- true }() c1 := make(chan int) c2 := make(chan int) go func() { // func6 select { case <-c1: case <-c2: } }() var mu sync.Mutex mu.Lock() go func() { // func7 mu.Lock() mu.Unlock() }() var wg sync.WaitGroup wg.Add(1) go func() { // func8 wg.Wait() }() cv := sync.NewCond(&sync.Mutex{}) go func() { // func9 cv.L.Lock() cv.Wait() cv.L.Unlock() }() ln, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { log.Fatalf("failed to listen: %v", err) } go func() { // func10 c, err := ln.Accept() if err != nil { log.Printf("failed to accept: %v", err) return } c.Close() }() rp, wp, err := os.Pipe() if err != nil { log.Fatalf("failed to create a pipe: %v", err) } defer rp.Close() defer wp.Close() pipeReadDone := make(chan bool) go func() { // func11 var data [1]byte rp.Read(data[:]) pipeReadDone <- true }() time.Sleep(100 * time.Millisecond) runtime.GC() runtime.Gosched() time.Sleep(100 * time.Millisecond) // the last chance for the goroutines above to block done1 <- true <-done2 select { case c1 <- 0: case c2 <- 0: } mu.Unlock() wg.Done() cv.Signal() c, err := net.Dial("tcp", ln.Addr().String()) if err != nil { log.Fatalf("failed to dial: %v", err) } c.Close() var data [1]byte wp.Write(data[:]) <-pipeReadDone oldGoMaxProcs := runtime.GOMAXPROCS(0) runtime.GOMAXPROCS(oldGoMaxProcs + 1) trace.Stop() runtime.GOMAXPROCS(oldGoMaxProcs) }