Source file src/internal/trace/testdata/testprog/stacks.go

     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  
     9  package main
    10  
    11  import (
    12  	"log"
    13  	"net"
    14  	"os"
    15  	"runtime"
    16  	"runtime/trace"
    17  	"sync"
    18  	"time"
    19  )
    20  
    21  func 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  

View as plain text