github.com/hikaru7719/go@v0.0.0-20181025140707-c8b2ac68906a/src/runtime/testdata/testprog/traceback_ancestors.go (about)

     1  // Copyright 2018 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  )
    11  
    12  func init() {
    13  	register("TracebackAncestors", TracebackAncestors)
    14  }
    15  
    16  const numGoroutines = 3
    17  const numFrames = 2
    18  
    19  func TracebackAncestors() {
    20  	w := make(chan struct{})
    21  	recurseThenCallGo(w, numGoroutines, numFrames)
    22  	<-w
    23  	printStack()
    24  	close(w)
    25  }
    26  
    27  func printStack() {
    28  	buf := make([]byte, 1024)
    29  	for {
    30  		n := runtime.Stack(buf, true)
    31  		if n < len(buf) {
    32  			fmt.Print(string(buf[:n]))
    33  			return
    34  		}
    35  		buf = make([]byte, 2*len(buf))
    36  	}
    37  }
    38  
    39  func recurseThenCallGo(w chan struct{}, frames int, goroutines int) {
    40  	if frames == 0 {
    41  		// Signal to TracebackAncestors that we are done recursing and starting goroutines.
    42  		w <- struct{}{}
    43  		<-w
    44  		return
    45  	}
    46  	if goroutines == 0 {
    47  		// Start the next goroutine now that there are no more recursions left
    48  		// for this current goroutine.
    49  		go recurseThenCallGo(w, frames-1, numFrames)
    50  		return
    51  	}
    52  	recurseThenCallGo(w, frames, goroutines-1)
    53  }