blob: 4872189f16beeb7631ead4466121633acc12a5b4 [file] [log] [blame]
Alex Brainmanafe0e972012-05-30 15:10:54 +10001// Copyright 2012 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// +build cgo
6
7package runtime_test
8
9import (
Ian Lance Taylor84e80802016-04-29 15:20:27 -070010 "bytes"
Ian Lance Taylor8d94b9b2016-02-25 21:16:45 -080011 "fmt"
Ian Lance Taylorc8e7b342016-02-18 11:04:05 -080012 "internal/testenv"
Mohit Agarwal4d6788e2016-05-05 00:04:54 +053013 "os"
Shenghou Ma865e5e92015-01-03 00:12:34 -050014 "os/exec"
Dmitriy Vyukov1590abe2013-08-08 00:04:28 +040015 "runtime"
Alex Brainman923299a2017-10-30 20:00:54 +110016 "strconv"
Russ Coxc4efaac2014-10-28 21:53:09 -040017 "strings"
Alex Brainmanafe0e972012-05-30 15:10:54 +100018 "testing"
Ian Lance Taylorc8e7b342016-02-18 11:04:05 -080019 "time"
Alex Brainmanafe0e972012-05-30 15:10:54 +100020)
21
22func TestCgoCrashHandler(t *testing.T) {
Brad Fitzpatrick23416312016-11-04 05:28:01 +000023 t.Parallel()
Dmitriy Vyukov06a488f2013-02-20 12:15:02 +040024 testCrashHandler(t, true)
Alex Brainmanafe0e972012-05-30 15:10:54 +100025}
Shenghou Ma6ecb39f2013-02-28 16:07:26 +080026
27func TestCgoSignalDeadlock(t *testing.T) {
Ian Lance Taylor7e172502017-07-12 20:51:15 -070028 // Don't call t.Parallel, since too much work going on at the
29 // same time can cause the testprogcgo code to overrun its
30 // timeouts (issue #18598).
31
Dmitriy Vyukov1590abe2013-08-08 00:04:28 +040032 if testing.Short() && runtime.GOOS == "windows" {
33 t.Skip("Skipping in short mode") // takes up to 64 seconds
34 }
Russ Cox8d5ff2e2015-12-21 10:29:21 -050035 got := runTestProg(t, "testprogcgo", "CgoSignalDeadlock")
Shenghou Ma6ecb39f2013-02-28 16:07:26 +080036 want := "OK\n"
37 if got != want {
Russ Cox8d5ff2e2015-12-21 10:29:21 -050038 t.Fatalf("expected %q, but got:\n%s", want, got)
Shenghou Ma6ecb39f2013-02-28 16:07:26 +080039 }
40}
41
Dmitriy Vyukov326ae8d2013-08-08 00:31:52 +040042func TestCgoTraceback(t *testing.T) {
Brad Fitzpatrick23416312016-11-04 05:28:01 +000043 t.Parallel()
Russ Cox8d5ff2e2015-12-21 10:29:21 -050044 got := runTestProg(t, "testprogcgo", "CgoTraceback")
Dmitriy Vyukov326ae8d2013-08-08 00:31:52 +040045 want := "OK\n"
46 if got != want {
Russ Cox8d5ff2e2015-12-21 10:29:21 -050047 t.Fatalf("expected %q, but got:\n%s", want, got)
Dmitriy Vyukov326ae8d2013-08-08 00:31:52 +040048 }
49}
50
Russ Coxfde39262015-07-29 16:16:13 -040051func TestCgoCallbackGC(t *testing.T) {
Brad Fitzpatrick23416312016-11-04 05:28:01 +000052 t.Parallel()
Josh Bleecher Snyder604efe12016-08-17 16:22:24 -070053 switch runtime.GOOS {
54 case "plan9", "windows":
Russ Coxfde39262015-07-29 16:16:13 -040055 t.Skipf("no pthreads on %s", runtime.GOOS)
56 }
Dave Cheney98400422015-09-11 10:15:17 +100057 if testing.Short() {
58 switch {
59 case runtime.GOOS == "dragonfly":
60 t.Skip("see golang.org/issue/11990")
61 case runtime.GOOS == "linux" && runtime.GOARCH == "arm":
62 t.Skip("too slow for arm builders")
Cherry Zhangbcd4b842016-05-04 22:07:50 -070063 case runtime.GOOS == "linux" && (runtime.GOARCH == "mips64" || runtime.GOARCH == "mips64le"):
64 t.Skip("too slow for mips64x builders")
Dave Cheney98400422015-09-11 10:15:17 +100065 }
Mikio Hara5e15e282015-08-03 12:43:25 +090066 }
Russ Cox8d5ff2e2015-12-21 10:29:21 -050067 got := runTestProg(t, "testprogcgo", "CgoCallbackGC")
Russ Coxfde39262015-07-29 16:16:13 -040068 want := "OK\n"
69 if got != want {
Russ Cox8d5ff2e2015-12-21 10:29:21 -050070 t.Fatalf("expected %q, but got:\n%s", want, got)
Russ Coxfde39262015-07-29 16:16:13 -040071 }
72}
73
Russ Coxc4efaac2014-10-28 21:53:09 -040074func TestCgoExternalThreadPanic(t *testing.T) {
Brad Fitzpatrick23416312016-11-04 05:28:01 +000075 t.Parallel()
Alex Brainmanf9c4c162014-10-30 10:24:37 +110076 if runtime.GOOS == "plan9" {
Russ Cox3ce6a4f2014-10-29 00:02:29 -040077 t.Skipf("no pthreads on %s", runtime.GOOS)
78 }
Russ Cox8d5ff2e2015-12-21 10:29:21 -050079 got := runTestProg(t, "testprogcgo", "CgoExternalThreadPanic")
Russ Coxc4efaac2014-10-28 21:53:09 -040080 want := "panic: BOOM"
81 if !strings.Contains(got, want) {
82 t.Fatalf("want failure containing %q. output:\n%s\n", want, got)
83 }
84}
85
Shenghou Ma5da9c8c2014-12-27 19:15:38 -050086func TestCgoExternalThreadSIGPROF(t *testing.T) {
Brad Fitzpatrick23416312016-11-04 05:28:01 +000087 t.Parallel()
Shenghou Ma5da9c8c2014-12-27 19:15:38 -050088 // issue 9456.
Shenghou Ma2cbe27a2015-01-01 01:10:39 -050089 switch runtime.GOOS {
90 case "plan9", "windows":
Shenghou Ma5da9c8c2014-12-27 19:15:38 -050091 t.Skipf("no pthreads on %s", runtime.GOOS)
92 }
Clément Chigotd24d25b2019-02-21 10:45:40 +010093 if runtime.GOARCH == "ppc64" && runtime.GOOS == "linux" {
Austin Clementsaf7ca8d2014-12-16 18:34:55 -050094 // TODO(austin) External linking not implemented on
Clément Chigotd24d25b2019-02-21 10:45:40 +010095 // linux/ppc64 (issue #8912)
Austin Clementsaf7ca8d2014-12-16 18:34:55 -050096 t.Skipf("no external linking on ppc64")
97 }
Ian Lance Taylore5421e22016-10-05 07:31:11 -070098
99 exe, err := buildTestProg(t, "testprogcgo", "-tags=threadprof")
100 if err != nil {
101 t.Fatal(err)
102 }
103
Daniel Martí0d8a3b22017-09-13 15:04:16 +0200104 got, err := testenv.CleanCmdEnv(exec.Command(exe, "CgoExternalThreadSIGPROF")).CombinedOutput()
Ian Lance Taylore5421e22016-10-05 07:31:11 -0700105 if err != nil {
106 t.Fatalf("exit status: %v\n%s", err, got)
107 }
108
109 if want := "OK\n"; string(got) != want {
Russ Cox8d5ff2e2015-12-21 10:29:21 -0500110 t.Fatalf("expected %q, but got:\n%s", want, got)
Shenghou Ma5da9c8c2014-12-27 19:15:38 -0500111 }
112}
113
Ian Lance Taylor872b1682015-07-21 22:34:48 -0700114func TestCgoExternalThreadSignal(t *testing.T) {
Brad Fitzpatrick23416312016-11-04 05:28:01 +0000115 t.Parallel()
Ian Lance Taylor872b1682015-07-21 22:34:48 -0700116 // issue 10139
117 switch runtime.GOOS {
118 case "plan9", "windows":
119 t.Skipf("no pthreads on %s", runtime.GOOS)
120 }
Ian Lance Taylore5421e22016-10-05 07:31:11 -0700121
122 exe, err := buildTestProg(t, "testprogcgo", "-tags=threadprof")
123 if err != nil {
124 t.Fatal(err)
125 }
126
Daniel Martí0d8a3b22017-09-13 15:04:16 +0200127 got, err := testenv.CleanCmdEnv(exec.Command(exe, "CgoExternalThreadSIGPROF")).CombinedOutput()
Ian Lance Taylore5421e22016-10-05 07:31:11 -0700128 if err != nil {
129 t.Fatalf("exit status: %v\n%s", err, got)
130 }
131
132 want := []byte("OK\n")
133 if !bytes.Equal(got, want) {
Russ Cox8d5ff2e2015-12-21 10:29:21 -0500134 t.Fatalf("expected %q, but got:\n%s", want, got)
Ian Lance Taylor872b1682015-07-21 22:34:48 -0700135 }
136}
137
Alex Brainman9b691962015-03-16 15:46:22 +1100138func TestCgoDLLImports(t *testing.T) {
139 // test issue 9356
140 if runtime.GOOS != "windows" {
141 t.Skip("skipping windows specific test")
142 }
Russ Cox8d5ff2e2015-12-21 10:29:21 -0500143 got := runTestProg(t, "testprogcgo", "CgoDLLImportsMain")
Alex Brainman9b691962015-03-16 15:46:22 +1100144 want := "OK\n"
145 if got != want {
146 t.Fatalf("expected %q, but got %v", want, got)
147 }
148}
Ian Lance Taylor70c9a812015-12-19 10:17:10 -0800149
150func TestCgoExecSignalMask(t *testing.T) {
Brad Fitzpatrick23416312016-11-04 05:28:01 +0000151 t.Parallel()
Ian Lance Taylor70c9a812015-12-19 10:17:10 -0800152 // Test issue 13164.
153 switch runtime.GOOS {
154 case "windows", "plan9":
155 t.Skipf("skipping signal mask test on %s", runtime.GOOS)
156 }
157 got := runTestProg(t, "testprogcgo", "CgoExecSignalMask")
158 want := "OK\n"
159 if got != want {
160 t.Errorf("expected %q, got %v", want, got)
161 }
162}
Ian Lance Taylorc02aa462016-01-08 16:56:02 -0800163
164func TestEnsureDropM(t *testing.T) {
Brad Fitzpatrick23416312016-11-04 05:28:01 +0000165 t.Parallel()
Ian Lance Taylorc02aa462016-01-08 16:56:02 -0800166 // Test for issue 13881.
Ian Lance Taylor92709732016-01-18 09:01:48 -0800167 switch runtime.GOOS {
168 case "windows", "plan9":
169 t.Skipf("skipping dropm test on %s", runtime.GOOS)
170 }
Ian Lance Taylorc02aa462016-01-08 16:56:02 -0800171 got := runTestProg(t, "testprogcgo", "EnsureDropM")
172 want := "OK\n"
173 if got != want {
174 t.Errorf("expected %q, got %v", want, got)
175 }
176}
Ian Lance Taylorc8e7b342016-02-18 11:04:05 -0800177
178// Test for issue 14387.
179// Test that the program that doesn't need any cgo pointer checking
180// takes about the same amount of time with it as without it.
181func TestCgoCheckBytes(t *testing.T) {
Brad Fitzpatrick23416312016-11-04 05:28:01 +0000182 t.Parallel()
Ian Lance Taylorc8e7b342016-02-18 11:04:05 -0800183 // Make sure we don't count the build time as part of the run time.
184 testenv.MustHaveGoBuild(t)
185 exe, err := buildTestProg(t, "testprogcgo")
186 if err != nil {
187 t.Fatal(err)
188 }
189
Ian Lance Taylor8d94b9b2016-02-25 21:16:45 -0800190 // Try it 10 times to avoid flakiness.
191 const tries = 10
192 var tot1, tot2 time.Duration
193 for i := 0; i < tries; i++ {
Daniel Martí0d8a3b22017-09-13 15:04:16 +0200194 cmd := testenv.CleanCmdEnv(exec.Command(exe, "CgoCheckBytes"))
Ian Lance Taylor8d94b9b2016-02-25 21:16:45 -0800195 cmd.Env = append(cmd.Env, "GODEBUG=cgocheck=0", fmt.Sprintf("GO_CGOCHECKBYTES_TRY=%d", i))
Ian Lance Taylorc8e7b342016-02-18 11:04:05 -0800196
Ian Lance Taylor8d94b9b2016-02-25 21:16:45 -0800197 start := time.Now()
198 cmd.Run()
199 d1 := time.Since(start)
Ian Lance Taylorc8e7b342016-02-18 11:04:05 -0800200
Daniel Martí0d8a3b22017-09-13 15:04:16 +0200201 cmd = testenv.CleanCmdEnv(exec.Command(exe, "CgoCheckBytes"))
Ian Lance Taylor8d94b9b2016-02-25 21:16:45 -0800202 cmd.Env = append(cmd.Env, fmt.Sprintf("GO_CGOCHECKBYTES_TRY=%d", i))
Ian Lance Taylorc8e7b342016-02-18 11:04:05 -0800203
Ian Lance Taylor8d94b9b2016-02-25 21:16:45 -0800204 start = time.Now()
205 cmd.Run()
206 d2 := time.Since(start)
Ian Lance Taylorc8e7b342016-02-18 11:04:05 -0800207
Ian Lance Taylor8d94b9b2016-02-25 21:16:45 -0800208 if d1*20 > d2 {
209 // The slow version (d2) was less than 20 times
210 // slower than the fast version (d1), so OK.
211 return
212 }
213
214 tot1 += d1
215 tot2 += d2
Ian Lance Taylorc8e7b342016-02-18 11:04:05 -0800216 }
Ian Lance Taylor8d94b9b2016-02-25 21:16:45 -0800217
218 t.Errorf("cgo check too slow: got %v, expected at most %v", tot2/tries, (tot1/tries)*20)
Ian Lance Taylorc8e7b342016-02-18 11:04:05 -0800219}
Shenghou Mae9603022016-02-21 13:56:08 -0500220
221func TestCgoPanicDeadlock(t *testing.T) {
Brad Fitzpatrick23416312016-11-04 05:28:01 +0000222 t.Parallel()
Shenghou Mae9603022016-02-21 13:56:08 -0500223 // test issue 14432
224 got := runTestProg(t, "testprogcgo", "CgoPanicDeadlock")
225 want := "panic: cgo error\n\n"
226 if !strings.HasPrefix(got, want) {
227 t.Fatalf("output does not start with %q:\n%s", want, got)
228 }
229}
Ian Lance Taylor17161622016-03-04 11:29:55 -0800230
231func TestCgoCCodeSIGPROF(t *testing.T) {
Brad Fitzpatrick23416312016-11-04 05:28:01 +0000232 t.Parallel()
Ian Lance Taylor17161622016-03-04 11:29:55 -0800233 got := runTestProg(t, "testprogcgo", "CgoCCodeSIGPROF")
234 want := "OK\n"
235 if got != want {
236 t.Errorf("expected %q got %v", want, got)
237 }
238}
Ian Lance Taylorea306ae2015-12-11 17:16:48 -0800239
240func TestCgoCrashTraceback(t *testing.T) {
Brad Fitzpatrick23416312016-11-04 05:28:01 +0000241 t.Parallel()
Nikhil Benesch5929ead2018-03-24 18:51:01 -0400242 switch platform := runtime.GOOS + "/" + runtime.GOARCH; platform {
243 case "darwin/amd64":
244 case "linux/amd64":
245 case "linux/ppc64le":
246 default:
247 t.Skipf("not yet supported on %s", platform)
Ian Lance Taylorea306ae2015-12-11 17:16:48 -0800248 }
249 got := runTestProg(t, "testprogcgo", "CrashTraceback")
250 for i := 1; i <= 3; i++ {
251 if !strings.Contains(got, fmt.Sprintf("cgo symbolizer:%d", i)) {
252 t.Errorf("missing cgo symbolizer:%d", i)
253 }
254 }
255}
Ian Lance Taylor5f9a8702016-04-27 14:18:29 -0700256
257func TestCgoTracebackContext(t *testing.T) {
Brad Fitzpatrick23416312016-11-04 05:28:01 +0000258 t.Parallel()
Ian Lance Taylor5f9a8702016-04-27 14:18:29 -0700259 got := runTestProg(t, "testprogcgo", "TracebackContext")
260 want := "OK\n"
261 if got != want {
262 t.Errorf("expected %q got %v", want, got)
263 }
264}
Ian Lance Taylor84e80802016-04-29 15:20:27 -0700265
Mark Pulford0f0b1082018-11-30 21:12:06 +1100266func testCgoPprof(t *testing.T, buildArg, runArg, top, bottom string) {
Brad Fitzpatrick23416312016-11-04 05:28:01 +0000267 t.Parallel()
Cherry Zhang6fd1f822017-10-20 14:26:28 -0400268 if runtime.GOOS != "linux" || (runtime.GOARCH != "amd64" && runtime.GOARCH != "ppc64le") {
Ian Lance Taylor84e80802016-04-29 15:20:27 -0700269 t.Skipf("not yet supported on %s/%s", runtime.GOOS, runtime.GOARCH)
270 }
271 testenv.MustHaveGoRun(t)
272
Ian Lance Taylor84d8aff2016-06-07 21:46:25 -0700273 exe, err := buildTestProg(t, "testprogcgo", buildArg)
Ian Lance Taylor84e80802016-04-29 15:20:27 -0700274 if err != nil {
275 t.Fatal(err)
276 }
277
Mark Pulforda908e092020-02-14 08:34:31 +1100278 // pprofCgoTraceback is called whenever CGO code is executing and a signal
279 // is received. Disable signal preemption to increase the likelihood at
280 // least one SIGPROF signal fired to capture a sample. See issue #37201.
281 cmd := testenv.CleanCmdEnv(exec.Command(exe, runArg))
282 cmd.Env = append(cmd.Env, "GODEBUG=asyncpreemptoff=1")
283
284 got, err := cmd.CombinedOutput()
Ian Lance Taylor84e80802016-04-29 15:20:27 -0700285 if err != nil {
Brad Fitzpatrick34ee8ec2017-04-25 04:59:14 +0000286 if testenv.Builder() == "linux-amd64-alpine" {
Brad Fitzpatrick16271b82017-04-25 02:46:06 +0000287 // See Issue 18243 and Issue 19938.
288 t.Skipf("Skipping failing test on Alpine (golang.org/issue/18243). Ignoring error: %v", err)
289 }
Josh Bleecher Snyderf248cd32019-04-15 17:55:58 -0700290 t.Fatalf("%s\n\n%v", got, err)
Ian Lance Taylor84e80802016-04-29 15:20:27 -0700291 }
292 fn := strings.TrimSpace(string(got))
Mohit Agarwal4d6788e2016-05-05 00:04:54 +0530293 defer os.Remove(fn)
Ian Lance Taylor84e80802016-04-29 15:20:27 -0700294
Russ Cox8c24e522017-02-17 15:27:12 -0500295 for try := 0; try < 2; try++ {
Mark Pulford0f0b1082018-11-30 21:12:06 +1100296 cmd := testenv.CleanCmdEnv(exec.Command(testenv.GoToolPath(t), "tool", "pprof", "-traces"))
Russ Cox8c24e522017-02-17 15:27:12 -0500297 // Check that pprof works both with and without explicit executable on command line.
298 if try == 0 {
299 cmd.Args = append(cmd.Args, exe, fn)
300 } else {
301 cmd.Args = append(cmd.Args, fn)
Ian Lance Taylor659b9a12016-06-20 09:16:17 -0700302 }
Ian Lance Taylor659b9a12016-06-20 09:16:17 -0700303
Russ Cox8c24e522017-02-17 15:27:12 -0500304 found := false
305 for i, e := range cmd.Env {
306 if strings.HasPrefix(e, "PPROF_TMPDIR=") {
307 cmd.Env[i] = "PPROF_TMPDIR=" + os.TempDir()
308 found = true
309 break
310 }
311 }
312 if !found {
313 cmd.Env = append(cmd.Env, "PPROF_TMPDIR="+os.TempDir())
314 }
Ian Lance Taylor84e80802016-04-29 15:20:27 -0700315
Mark Pulford0f0b1082018-11-30 21:12:06 +1100316 out, err := cmd.CombinedOutput()
317 t.Logf("%s:\n%s", cmd.Args, out)
Russ Cox8c24e522017-02-17 15:27:12 -0500318 if err != nil {
319 t.Error(err)
Mark Pulford0f0b1082018-11-30 21:12:06 +1100320 continue
321 }
322
323 trace := findTrace(string(out), top)
324 if len(trace) == 0 {
325 t.Errorf("%s traceback missing.", top)
326 continue
327 }
328 if trace[len(trace)-1] != bottom {
329 t.Errorf("invalid traceback origin: got=%v; want=[%s ... %s]", trace, top, bottom)
Russ Cox8c24e522017-02-17 15:27:12 -0500330 }
Ian Lance Taylor84e80802016-04-29 15:20:27 -0700331 }
332}
Ian Lance Taylor42232942016-05-27 16:03:44 -0700333
Ian Lance Taylor84d8aff2016-06-07 21:46:25 -0700334func TestCgoPprof(t *testing.T) {
Mark Pulford0f0b1082018-11-30 21:12:06 +1100335 testCgoPprof(t, "", "CgoPprof", "cpuHog", "runtime.main")
Ian Lance Taylor84d8aff2016-06-07 21:46:25 -0700336}
337
Ian Lance Taylor42232942016-05-27 16:03:44 -0700338func TestCgoPprofPIE(t *testing.T) {
Mark Pulford0f0b1082018-11-30 21:12:06 +1100339 testCgoPprof(t, "-buildmode=pie", "CgoPprof", "cpuHog", "runtime.main")
Ian Lance Taylor84d8aff2016-06-07 21:46:25 -0700340}
Ian Lance Taylor42232942016-05-27 16:03:44 -0700341
Ian Lance Taylor84d8aff2016-06-07 21:46:25 -0700342func TestCgoPprofThread(t *testing.T) {
Mark Pulford0f0b1082018-11-30 21:12:06 +1100343 testCgoPprof(t, "", "CgoPprofThread", "cpuHogThread", "cpuHogThread2")
Ian Lance Taylor42232942016-05-27 16:03:44 -0700344}
Ian Lance Taylor9d8522f2016-09-21 09:44:40 -0700345
Ian Lance Taylord03e8b22016-10-04 07:11:55 -0700346func TestCgoPprofThreadNoTraceback(t *testing.T) {
Mark Pulford0f0b1082018-11-30 21:12:06 +1100347 testCgoPprof(t, "", "CgoPprofThreadNoTraceback", "cpuHogThread", "runtime._ExternalCode")
Ian Lance Taylord03e8b22016-10-04 07:11:55 -0700348}
349
Ian Lance Taylor9d8522f2016-09-21 09:44:40 -0700350func TestRaceProf(t *testing.T) {
Tim Wright131901e2018-03-26 19:00:15 -0700351 if (runtime.GOOS != "linux" && runtime.GOOS != "freebsd") || runtime.GOARCH != "amd64" {
Ian Lance Taylor9d8522f2016-09-21 09:44:40 -0700352 t.Skipf("not yet supported on %s/%s", runtime.GOOS, runtime.GOARCH)
353 }
354
355 testenv.MustHaveGoRun(t)
356
357 // This test requires building various packages with -race, so
358 // it's somewhat slow.
359 if testing.Short() {
360 t.Skip("skipping test in -short mode")
361 }
362
363 exe, err := buildTestProg(t, "testprogcgo", "-race")
364 if err != nil {
365 t.Fatal(err)
366 }
367
Daniel Martí0d8a3b22017-09-13 15:04:16 +0200368 got, err := testenv.CleanCmdEnv(exec.Command(exe, "CgoRaceprof")).CombinedOutput()
Ian Lance Taylor9d8522f2016-09-21 09:44:40 -0700369 if err != nil {
370 t.Fatal(err)
371 }
372 want := "OK\n"
373 if string(got) != want {
374 t.Errorf("expected %q got %s", want, got)
375 }
376}
Ian Lance Taylor6c13a1d2016-10-03 16:58:34 -0700377
378func TestRaceSignal(t *testing.T) {
Brad Fitzpatrick23416312016-11-04 05:28:01 +0000379 t.Parallel()
Tim Wright131901e2018-03-26 19:00:15 -0700380 if (runtime.GOOS != "linux" && runtime.GOOS != "freebsd") || runtime.GOARCH != "amd64" {
Ian Lance Taylor6c13a1d2016-10-03 16:58:34 -0700381 t.Skipf("not yet supported on %s/%s", runtime.GOOS, runtime.GOARCH)
382 }
383
384 testenv.MustHaveGoRun(t)
385
386 // This test requires building various packages with -race, so
387 // it's somewhat slow.
388 if testing.Short() {
389 t.Skip("skipping test in -short mode")
390 }
391
392 exe, err := buildTestProg(t, "testprogcgo", "-race")
393 if err != nil {
394 t.Fatal(err)
395 }
396
Daniel Martí0d8a3b22017-09-13 15:04:16 +0200397 got, err := testenv.CleanCmdEnv(exec.Command(exe, "CgoRaceSignal")).CombinedOutput()
Ian Lance Taylor6c13a1d2016-10-03 16:58:34 -0700398 if err != nil {
399 t.Logf("%s\n", got)
400 t.Fatal(err)
401 }
402 want := "OK\n"
403 if string(got) != want {
404 t.Errorf("expected %q got %s", want, got)
405 }
406}
Austin Clements4e7067c2017-06-06 18:37:59 -0400407
408func TestCgoNumGoroutine(t *testing.T) {
Ian Lance Taylor03a4a5c2017-06-14 10:17:29 -0700409 switch runtime.GOOS {
410 case "windows", "plan9":
411 t.Skipf("skipping numgoroutine test on %s", runtime.GOOS)
412 }
Austin Clements4e7067c2017-06-06 18:37:59 -0400413 t.Parallel()
414 got := runTestProg(t, "testprogcgo", "NumGoroutine")
415 want := "OK\n"
416 if got != want {
417 t.Errorf("expected %q got %v", want, got)
418 }
419}
Elias Naur5500c9c2017-07-18 14:17:57 +0200420
421func TestCatchPanic(t *testing.T) {
422 t.Parallel()
423 switch runtime.GOOS {
424 case "plan9", "windows":
425 t.Skipf("no signals on %s", runtime.GOOS)
426 case "darwin":
427 if runtime.GOARCH == "amd64" {
428 t.Skipf("crash() on darwin/amd64 doesn't raise SIGABRT")
429 }
430 }
431
432 testenv.MustHaveGoRun(t)
433
434 exe, err := buildTestProg(t, "testprogcgo")
435 if err != nil {
436 t.Fatal(err)
437 }
438
Elias Naurc3189ce2017-08-19 16:59:19 +0200439 for _, early := range []bool{true, false} {
Daniel Martí0d8a3b22017-09-13 15:04:16 +0200440 cmd := testenv.CleanCmdEnv(exec.Command(exe, "CgoCatchPanic"))
Elias Naurc3189ce2017-08-19 16:59:19 +0200441 // Make sure a panic results in a crash.
442 cmd.Env = append(cmd.Env, "GOTRACEBACK=crash")
443 if early {
444 // Tell testprogcgo to install an early signal handler for SIGABRT
445 cmd.Env = append(cmd.Env, "CGOCATCHPANIC_EARLY_HANDLER=1")
446 }
447 if out, err := cmd.CombinedOutput(); err != nil {
448 t.Errorf("testprogcgo CgoCatchPanic failed: %v\n%s", err, out)
449 }
Elias Naur5500c9c2017-07-18 14:17:57 +0200450 }
451}
Austin Clements4f34a522017-06-16 16:21:12 -0400452
453func TestCgoLockOSThreadExit(t *testing.T) {
454 switch runtime.GOOS {
455 case "plan9", "windows":
456 t.Skipf("no pthreads on %s", runtime.GOOS)
457 }
458 t.Parallel()
459 testLockOSThreadExit(t, "testprogcgo")
460}
Alex Brainman923299a2017-10-30 20:00:54 +1100461
Alex Brainmancea92e82017-11-14 12:51:58 +1100462func TestWindowsStackMemoryCgo(t *testing.T) {
463 if runtime.GOOS != "windows" {
464 t.Skip("skipping windows specific test")
465 }
466 testenv.SkipFlaky(t, 22575)
467 o := runTestProg(t, "testprogcgo", "StackMemory")
Alex Brainman923299a2017-10-30 20:00:54 +1100468 stackUsage, err := strconv.Atoi(o)
469 if err != nil {
470 t.Fatalf("Failed to read stack usage: %v", err)
471 }
472 if expected, got := 100<<10, stackUsage; got > expected {
473 t.Fatalf("expected < %d bytes of memory per thread, got %d", expected, got)
474 }
475}
Austin Clements292558b2017-11-30 22:09:35 -0500476
477func TestSigStackSwapping(t *testing.T) {
478 switch runtime.GOOS {
479 case "plan9", "windows":
Russ Coxde14b2f2017-12-13 14:57:44 -0500480 t.Skipf("no sigaltstack on %s", runtime.GOOS)
Austin Clements292558b2017-11-30 22:09:35 -0500481 }
482 t.Parallel()
483 got := runTestProg(t, "testprogcgo", "SigStack")
484 want := "OK\n"
485 if got != want {
486 t.Errorf("expected %q got %v", want, got)
487 }
488}
Austin Clementsebe38b82018-01-30 16:03:51 -0500489
490func TestCgoTracebackSigpanic(t *testing.T) {
491 // Test unwinding over a sigpanic in C code without a C
492 // symbolizer. See issue #23576.
493 if runtime.GOOS == "windows" {
494 // On Windows if we get an exception in C code, we let
495 // the Windows exception handler unwind it, rather
496 // than injecting a sigpanic.
497 t.Skip("no sigpanic in C on windows")
498 }
499 t.Parallel()
500 got := runTestProg(t, "testprogcgo", "TracebackSigpanic")
501 want := "runtime.sigpanic"
502 if !strings.Contains(got, want) {
503 t.Fatalf("want failure containing %q. output:\n%s\n", want, got)
504 }
505 nowant := "unexpected return pc"
506 if strings.Contains(got, nowant) {
507 t.Fatalf("failure incorrectly contains %q. output:\n%s\n", nowant, got)
508 }
509}
Austin Clements99e9be82018-06-21 12:08:36 -0400510
511// Test that C code called via cgo can use large Windows thread stacks
512// and call back in to Go without crashing. See issue #20975.
513//
514// See also TestBigStackCallbackSyscall.
515func TestBigStackCallbackCgo(t *testing.T) {
516 if runtime.GOOS != "windows" {
517 t.Skip("skipping windows specific test")
518 }
519 t.Parallel()
520 got := runTestProg(t, "testprogcgo", "BigStack")
521 want := "OK\n"
522 if got != want {
523 t.Errorf("expected %q got %v", want, got)
524 }
525}
Mark Pulford0f0b1082018-11-30 21:12:06 +1100526
527func nextTrace(lines []string) ([]string, []string) {
528 var trace []string
529 for n, line := range lines {
530 if strings.HasPrefix(line, "---") {
531 return trace, lines[n+1:]
532 }
533 fields := strings.Fields(strings.TrimSpace(line))
534 if len(fields) == 0 {
535 continue
536 }
537 // Last field contains the function name.
538 trace = append(trace, fields[len(fields)-1])
539 }
540 return nil, nil
541}
542
543func findTrace(text, top string) []string {
544 lines := strings.Split(text, "\n")
545 _, lines = nextTrace(lines) // Skip the header.
546 for len(lines) > 0 {
547 var t []string
548 t, lines = nextTrace(lines)
549 if len(t) == 0 {
550 continue
551 }
552 if t[0] == top {
553 return t
554 }
555 }
556 return nil
557}
Ian Lance Taylore5bd6e12020-04-18 20:11:46 -0700558
559func TestSegv(t *testing.T) {
560 switch runtime.GOOS {
561 case "plan9", "windows":
562 t.Skipf("no signals on %s", runtime.GOOS)
563 }
564
565 for _, test := range []string{"Segv", "SegvInCgo"} {
566 t.Run(test, func(t *testing.T) {
567 t.Parallel()
568 got := runTestProg(t, "testprogcgo", test)
569 t.Log(got)
570 if !strings.Contains(got, "SIGSEGV") {
571 t.Errorf("expected crash from signal")
572 }
573 })
574 }
575}
Ian Lance Taylor8c1db772020-05-07 21:34:54 -0700576
577// TestEINTR tests that we handle EINTR correctly.
578// See issue #20400 and friends.
579func TestEINTR(t *testing.T) {
580 switch runtime.GOOS {
581 case "plan9", "windows":
582 t.Skipf("no EINTR on %s", runtime.GOOS)
583 case "linux":
584 if runtime.GOARCH == "386" {
585 // On linux-386 the Go signal handler sets
586 // a restorer function that is not preserved
587 // by the C sigaction call in the test,
588 // causing the signal handler to crash when
589 // returning the normal code. The test is not
590 // architecture-specific, so just skip on 386
591 // rather than doing a complicated workaround.
592 t.Skip("skipping on linux-386; C sigaction does not preserve Go restorer")
593 }
594 }
595
596 t.Parallel()
597 output := runTestProg(t, "testprogcgo", "EINTR")
598 want := "OK\n"
599 if output != want {
600 t.Fatalf("want %s, got %s\n", want, output)
601 }
602}