1
2
3
4
5
6
7
8
9 package cgotest
10
11 import (
12 "bytes"
13 "crypto/md5"
14 "os"
15 "os/exec"
16 "runtime"
17 "syscall"
18 "testing"
19 "time"
20 )
21
22 func test18146(t *testing.T) {
23 if testing.Short() {
24 t.Skip("skipping in short mode")
25 }
26
27 if runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
28 t.Skipf("skipping flaky test on %s; see golang.org/issue/18202", runtime.GOOS)
29 }
30
31 if runtime.GOARCH == "mips" || runtime.GOARCH == "mips64" {
32 t.Skipf("skipping on %s", runtime.GOARCH)
33 }
34
35 attempts := 1000
36 threads := 4
37
38
39
40
41
42 var nproc int
43 setNproc := true
44 switch runtime.GOOS {
45 default:
46 setNproc = false
47 case "aix":
48 nproc = 9
49 case "linux":
50 nproc = 6
51 case "darwin", "dragonfly", "freebsd", "netbsd", "openbsd":
52 nproc = 7
53 }
54 if setNproc {
55 var rlim syscall.Rlimit
56 if syscall.Getrlimit(nproc, &rlim) == nil {
57 max := int(rlim.Cur) / (threads + 5)
58 if attempts > max {
59 t.Logf("lowering attempts from %d to %d for RLIMIT_NPROC", attempts, max)
60 attempts = max
61 }
62 }
63 }
64
65 if os.Getenv("test18146") == "exec" {
66 runtime.GOMAXPROCS(1)
67 for n := threads; n > 0; n-- {
68 go func() {
69 for {
70 _ = md5.Sum([]byte("Hello, !"))
71 }
72 }()
73 }
74 runtime.GOMAXPROCS(threads)
75 argv := append(os.Args, "-test.run=^$")
76 if err := syscall.Exec(os.Args[0], argv, os.Environ()); err != nil {
77 t.Fatal(err)
78 }
79 }
80
81 var cmds []*exec.Cmd
82 defer func() {
83 for _, cmd := range cmds {
84 cmd.Process.Kill()
85 }
86 }()
87
88 args := append(append([]string(nil), os.Args[1:]...), "-test.run=^Test18146$")
89 for n := attempts; n > 0; n-- {
90 cmd := exec.Command(os.Args[0], args...)
91 cmd.Env = append(os.Environ(), "test18146=exec")
92 buf := bytes.NewBuffer(nil)
93 cmd.Stdout = buf
94 cmd.Stderr = buf
95 if err := cmd.Start(); err != nil {
96
97
98
99
100 if pe, ok := err.(*os.PathError); ok {
101 err = pe.Err
102 }
103 if se, ok := err.(syscall.Errno); ok && (se == syscall.EAGAIN || se == syscall.EMFILE) {
104 time.Sleep(time.Millisecond)
105 continue
106 }
107
108 t.Error(err)
109 return
110 }
111 cmds = append(cmds, cmd)
112 }
113
114 failures := 0
115 for _, cmd := range cmds {
116 err := cmd.Wait()
117 if err == nil {
118 continue
119 }
120
121 t.Errorf("syscall.Exec failed: %v\n%s", err, cmd.Stdout)
122 failures++
123 }
124
125 if failures > 0 {
126 t.Logf("Failed %v of %v attempts.", failures, len(cmds))
127 }
128 }
129
View as plain text