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 a many interesting cases (network, syscalls, a little GC, busy goroutines,
6// blocked goroutines, LockOSThread, pipes, and GOMAXPROCS).
7
8//go:build ignore
9
10package main
11
12import (
13	"log"
14	"net"
15	"os"
16	"runtime"
17	"runtime/trace"
18	"sync"
19	"time"
20)
21
22func main() {
23	var wg sync.WaitGroup
24	done := make(chan bool)
25
26	// Create a goroutine blocked before tracing.
27	wg.Add(1)
28	go func() {
29		<-done
30		wg.Done()
31	}()
32
33	// Create a goroutine blocked in syscall before tracing.
34	rp, wp, err := os.Pipe()
35	if err != nil {
36		log.Fatalf("failed to create pipe: %v", err)
37	}
38	defer func() {
39		rp.Close()
40		wp.Close()
41	}()
42	wg.Add(1)
43	go func() {
44		var tmp [1]byte
45		rp.Read(tmp[:])
46		<-done
47		wg.Done()
48	}()
49	time.Sleep(time.Millisecond) // give the goroutine above time to block
50
51	if err := trace.Start(os.Stdout); err != nil {
52		log.Fatalf("failed to start tracing: %v", err)
53	}
54	defer trace.Stop()
55
56	procs := runtime.GOMAXPROCS(10)
57	time.Sleep(50 * time.Millisecond) // test proc stop/start events
58
59	go func() {
60		runtime.LockOSThread()
61		for {
62			select {
63			case <-done:
64				return
65			default:
66				runtime.Gosched()
67			}
68		}
69	}()
70
71	runtime.GC()
72	// Trigger GC from malloc.
73	n := 512
74	for i := 0; i < n; i++ {
75		_ = make([]byte, 1<<20)
76	}
77
78	// Create a bunch of busy goroutines to load all Ps.
79	for p := 0; p < 10; p++ {
80		wg.Add(1)
81		go func() {
82			// Do something useful.
83			tmp := make([]byte, 1<<16)
84			for i := range tmp {
85				tmp[i]++
86			}
87			_ = tmp
88			<-done
89			wg.Done()
90		}()
91	}
92
93	// Block in syscall.
94	wg.Add(1)
95	go func() {
96		var tmp [1]byte
97		rp.Read(tmp[:])
98		<-done
99		wg.Done()
100	}()
101
102	// Test timers.
103	timerDone := make(chan bool)
104	go func() {
105		time.Sleep(time.Millisecond)
106		timerDone <- true
107	}()
108	<-timerDone
109
110	// A bit of network.
111	ln, err := net.Listen("tcp", "127.0.0.1:0")
112	if err != nil {
113		log.Fatalf("listen failed: %v", err)
114	}
115	defer ln.Close()
116	go func() {
117		c, err := ln.Accept()
118		if err != nil {
119			return
120		}
121		time.Sleep(time.Millisecond)
122		var buf [1]byte
123		c.Write(buf[:])
124		c.Close()
125	}()
126	c, err := net.Dial("tcp", ln.Addr().String())
127	if err != nil {
128		log.Fatalf("dial failed: %v", err)
129	}
130	var tmp [1]byte
131	c.Read(tmp[:])
132	c.Close()
133
134	go func() {
135		runtime.Gosched()
136		select {}
137	}()
138
139	// Unblock helper goroutines and wait them to finish.
140	wp.Write(tmp[:])
141	wp.Write(tmp[:])
142	close(done)
143	wg.Wait()
144
145	runtime.GOMAXPROCS(procs)
146}
147