1// Copyright 2017 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//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd
6// +build darwin dragonfly freebsd linux netbsd openbsd
7
8// This is in testprognet instead of testprog because testprog
9// must not import anything (like net, but also like os/signal)
10// that kicks off background goroutines during init.
11
12package main
13
14import (
15	"fmt"
16	"os"
17	"os/exec"
18	"os/signal"
19	"sync"
20	"syscall"
21	"time"
22)
23
24func init() {
25	register("SignalDuringExec", SignalDuringExec)
26	register("Nop", Nop)
27}
28
29func SignalDuringExec() {
30	pgrp := syscall.Getpgrp()
31
32	const tries = 10
33
34	var wg sync.WaitGroup
35	c := make(chan os.Signal, tries)
36	signal.Notify(c, syscall.SIGWINCH)
37	wg.Add(1)
38	go func() {
39		defer wg.Done()
40		for range c {
41		}
42	}()
43
44	for i := 0; i < tries; i++ {
45		time.Sleep(time.Microsecond)
46		wg.Add(2)
47		go func() {
48			defer wg.Done()
49			cmd := exec.Command(os.Args[0], "Nop")
50			cmd.Stdout = os.Stdout
51			cmd.Stderr = os.Stderr
52			if err := cmd.Run(); err != nil {
53				fmt.Printf("Start failed: %v", err)
54			}
55		}()
56		go func() {
57			defer wg.Done()
58			syscall.Kill(-pgrp, syscall.SIGWINCH)
59		}()
60	}
61
62	signal.Stop(c)
63	close(c)
64	wg.Wait()
65
66	fmt.Println("OK")
67}
68
69func Nop() {
70	// This is just for SignalDuringExec.
71}
72