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
5package main
6
7import (
8	"os"
9	"sync"
10	"syscall"
11)
12
13func main() {
14	if len(os.Args) < 2 {
15		panic("usage: nonblock <MODE> [PATH...]")
16	}
17	mode := os.Args[1]
18
19	ready := make(chan struct{})
20
21	var wg sync.WaitGroup
22	for _, path := range os.Args[2:] {
23		f, err := os.Open(path)
24		if err != nil {
25			panic(err)
26		}
27		switch mode {
28		case "os.OpenFile":
29		case "os.NewFile":
30			fd := f.Fd()
31			if err := syscall.SetNonblock(int(fd), true); err != nil {
32				panic(err)
33			}
34			f = os.NewFile(fd, path)
35		default:
36			panic("invalid test mode")
37		}
38
39		spawnWait := make(chan struct{})
40
41		wg.Add(1)
42		go func(f *os.File) {
43			defer f.Close()
44			defer wg.Done()
45
46			close(spawnWait)
47
48			<-ready
49
50			var buf [256]byte
51			n, err := f.Read(buf[:])
52			if err != nil {
53				panic(err)
54			}
55			os.Stderr.Write(buf[:n])
56		}(f)
57
58		// Spawn one goroutine at a time.
59		<-spawnWait
60	}
61
62	println("waiting")
63	close(ready)
64	wg.Wait()
65}
66