Source file
src/runtime/crash_cgo_test.go
1
2
3
4
5
6
7 package runtime_test
8
9 import (
10 "fmt"
11 "internal/asan"
12 "internal/goos"
13 "internal/msan"
14 "internal/race"
15 "internal/testenv"
16 "os"
17 "os/exec"
18 "path/filepath"
19 "runtime"
20 "strconv"
21 "strings"
22 "testing"
23 "time"
24 )
25
26 func TestCgoCrashHandler(t *testing.T) {
27 t.Parallel()
28 testCrashHandler(t, true)
29 }
30
31 func TestCgoSignalDeadlock(t *testing.T) {
32
33
34
35
36 if testing.Short() && runtime.GOOS == "windows" {
37 t.Skip("Skipping in short mode")
38 }
39 if runtime.GOOS == "freebsd" && race.Enabled {
40 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
41 }
42 got := runTestProg(t, "testprogcgo", "CgoSignalDeadlock")
43 want := "OK\n"
44 if got != want {
45 t.Fatalf("expected %q, but got:\n%s", want, got)
46 }
47 }
48
49 func TestCgoTraceback(t *testing.T) {
50 if runtime.GOOS == "freebsd" && race.Enabled {
51 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
52 }
53
54 t.Parallel()
55 got := runTestProg(t, "testprogcgo", "CgoTraceback")
56 want := "OK\n"
57 if got != want {
58 t.Fatalf("expected %q, but got:\n%s", want, got)
59 }
60 }
61
62 func TestCgoCallbackGC(t *testing.T) {
63 t.Parallel()
64 switch runtime.GOOS {
65 case "plan9", "windows":
66 t.Skipf("no pthreads on %s", runtime.GOOS)
67 }
68 if runtime.GOOS == "freebsd" && race.Enabled {
69 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
70 }
71 if testing.Short() {
72 switch {
73 case runtime.GOOS == "dragonfly":
74 t.Skip("see golang.org/issue/11990")
75 case runtime.GOOS == "linux" && runtime.GOARCH == "arm":
76 t.Skip("too slow for arm builders")
77 case runtime.GOOS == "linux" && (runtime.GOARCH == "mips64" || runtime.GOARCH == "mips64le"):
78 t.Skip("too slow for mips64x builders")
79 }
80 }
81 got := runTestProg(t, "testprogcgo", "CgoCallbackGC")
82 want := "OK\n"
83 if got != want {
84 t.Fatalf("expected %q, but got:\n%s", want, got)
85 }
86 }
87
88 func TestCgoCallbackPprof(t *testing.T) {
89 t.Parallel()
90 switch runtime.GOOS {
91 case "plan9", "windows":
92 t.Skipf("no pthreads on %s", runtime.GOOS)
93 }
94 if runtime.GOOS == "freebsd" && race.Enabled {
95 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
96 }
97 if testenv.CPUProfilingBroken() {
98 t.Skip("skipping on platform with broken profiling")
99 }
100
101 got := runTestProg(t, "testprogcgo", "CgoCallbackPprof")
102 if want := "OK\n"; got != want {
103 t.Fatalf("expected %q, but got:\n%s", want, got)
104 }
105 }
106
107 func TestCgoCallbackX15(t *testing.T) {
108 t.Parallel()
109 if runtime.GOARCH != "amd64" {
110 t.Skipf("X15 test only relevant on amd64")
111 }
112 if runtime.GOOS == "freebsd" && race.Enabled {
113 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
114 }
115
116 got := runTestProg(t, "testprogcgo", "CgoCallbackX15")
117 if want := "OK\n"; got != want {
118 t.Fatalf("expected %q, but got:\n%s", want, got)
119 }
120 }
121
122 func TestSecretCgo(t *testing.T) {
123 t.Parallel()
124 testenv.MustHaveGoBuild(t)
125 testenv.MustHaveCGO(t)
126
127 exe := filepath.Join(t.TempDir(), "secretcgo.exe")
128 cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", exe)
129 cmd.Dir = "testdata/testprogcgo"
130 cmd = testenv.CleanCmdEnv(cmd)
131 cmd.Env = append(cmd.Env, "GOEXPERIMENT=runtimesecret")
132 out, err := cmd.CombinedOutput()
133 if err != nil {
134 t.Fatalf("building testprogcgo with runtimesecret: %v\n%s", err, out)
135 }
136
137 got := runBuiltTestProg(t, exe, "SecretCgo")
138 if want := "OK\n"; got != want {
139 t.Fatalf("expected %q, got:\n%s", want, got)
140 }
141 }
142
143 func TestCgoExternalThreadPanic(t *testing.T) {
144 t.Parallel()
145 if runtime.GOOS == "plan9" {
146 t.Skipf("no pthreads on %s", runtime.GOOS)
147 }
148 if runtime.GOOS == "freebsd" && race.Enabled {
149 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
150 }
151 got := runTestProg(t, "testprogcgo", "CgoExternalThreadPanic")
152 want := "panic: BOOM"
153 if !strings.Contains(got, want) {
154 t.Fatalf("want failure containing %q. output:\n%s\n", want, got)
155 }
156 }
157
158 func TestCgoExternalThreadSIGPROF(t *testing.T) {
159 t.Parallel()
160
161 switch runtime.GOOS {
162 case "plan9", "windows":
163 t.Skipf("no pthreads on %s", runtime.GOOS)
164 }
165 if runtime.GOOS == "freebsd" && race.Enabled {
166 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
167 }
168
169 got := runTestProg(t, "testprogcgo", "CgoExternalThreadSIGPROF", "GO_START_SIGPROF_THREAD=1")
170 if want := "OK\n"; got != want {
171 t.Fatalf("expected %q, but got:\n%s", want, got)
172 }
173 }
174
175 func TestCgoExternalThreadSignal(t *testing.T) {
176 t.Parallel()
177
178 switch runtime.GOOS {
179 case "plan9", "windows":
180 t.Skipf("no pthreads on %s", runtime.GOOS)
181 }
182 if runtime.GOOS == "freebsd" && race.Enabled {
183 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
184 }
185
186 got := runTestProg(t, "testprogcgo", "CgoExternalThreadSignal")
187 if want := "OK\n"; got != want {
188 if runtime.GOOS == "ios" && strings.Contains(got, "C signal did not crash as expected") {
189 testenv.SkipFlaky(t, 59913)
190 }
191 t.Fatalf("expected %q, but got:\n%s", want, got)
192 }
193 }
194
195 func TestCgoDLLImports(t *testing.T) {
196
197 if runtime.GOOS != "windows" {
198 t.Skip("skipping windows specific test")
199 }
200 if runtime.GOOS == "freebsd" && race.Enabled {
201 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
202 }
203 got := runTestProg(t, "testprogcgo", "CgoDLLImportsMain")
204 want := "OK\n"
205 if got != want {
206 t.Fatalf("expected %q, but got %v", want, got)
207 }
208 }
209
210 func TestCgoExecSignalMask(t *testing.T) {
211 t.Parallel()
212
213 switch runtime.GOOS {
214 case "windows", "plan9":
215 t.Skipf("skipping signal mask test on %s", runtime.GOOS)
216 }
217 if runtime.GOOS == "freebsd" && race.Enabled {
218 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
219 }
220 got := runTestProg(t, "testprogcgo", "CgoExecSignalMask", "GOTRACEBACK=system")
221 want := "OK\n"
222 if got != want {
223 t.Errorf("expected %q, got %v", want, got)
224 }
225 }
226
227 func TestEnsureDropM(t *testing.T) {
228 t.Parallel()
229
230 switch runtime.GOOS {
231 case "windows", "plan9":
232 t.Skipf("skipping dropm test on %s", runtime.GOOS)
233 }
234 if runtime.GOOS == "freebsd" && race.Enabled {
235 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
236 }
237 got := runTestProg(t, "testprogcgo", "EnsureDropM")
238 want := "OK\n"
239 if got != want {
240 t.Errorf("expected %q, got %v", want, got)
241 }
242 }
243
244
245
246
247 func TestCgoCheckBytes(t *testing.T) {
248 t.Parallel()
249
250 testenv.MustHaveGoBuild(t)
251 if runtime.GOOS == "freebsd" && race.Enabled {
252 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
253 }
254 exe, err := buildTestProg(t, "testprogcgo")
255 if err != nil {
256 t.Fatal(err)
257 }
258
259
260 const tries = 10
261 var tot1, tot2 time.Duration
262 for i := 0; i < tries; i++ {
263 cmd := testenv.CleanCmdEnv(exec.Command(exe, "CgoCheckBytes"))
264 cmd.Env = append(cmd.Env, "GODEBUG=cgocheck=0", fmt.Sprintf("GO_CGOCHECKBYTES_TRY=%d", i))
265
266 start := time.Now()
267 cmd.Run()
268 d1 := time.Since(start)
269
270 cmd = testenv.CleanCmdEnv(exec.Command(exe, "CgoCheckBytes"))
271 cmd.Env = append(cmd.Env, fmt.Sprintf("GO_CGOCHECKBYTES_TRY=%d", i))
272
273 start = time.Now()
274 cmd.Run()
275 d2 := time.Since(start)
276
277 if d1*20 > d2 {
278
279
280 return
281 }
282
283 tot1 += d1
284 tot2 += d2
285 }
286
287 t.Errorf("cgo check too slow: got %v, expected at most %v", tot2/tries, (tot1/tries)*20)
288 }
289
290 func TestCgoPanicDeadlock(t *testing.T) {
291 t.Parallel()
292 if runtime.GOOS == "freebsd" && race.Enabled {
293 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
294 }
295
296 got := runTestProg(t, "testprogcgo", "CgoPanicDeadlock")
297 want := "panic: cgo error\n\n"
298 if !strings.HasPrefix(got, want) {
299 t.Fatalf("output does not start with %q:\n%s", want, got)
300 }
301 }
302
303 func TestCgoCCodeSIGPROF(t *testing.T) {
304 t.Parallel()
305 if runtime.GOOS == "freebsd" && race.Enabled {
306 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
307 }
308 got := runTestProg(t, "testprogcgo", "CgoCCodeSIGPROF")
309 want := "OK\n"
310 if got != want {
311 t.Errorf("expected %q got %v", want, got)
312 }
313 }
314
315 func TestCgoPprofCallback(t *testing.T) {
316 if testing.Short() {
317 t.Skip("skipping in short mode")
318 }
319 switch runtime.GOOS {
320 case "windows", "plan9":
321 t.Skipf("skipping cgo pprof callback test on %s", runtime.GOOS)
322 }
323 if runtime.GOOS == "freebsd" && race.Enabled {
324 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
325 }
326 got := runTestProg(t, "testprogcgo", "CgoPprofCallback")
327 want := "OK\n"
328 if got != want {
329 t.Errorf("expected %q got %v", want, got)
330 }
331 }
332
333 func TestCgoCrashTraceback(t *testing.T) {
334 t.Parallel()
335 switch platform := runtime.GOOS + "/" + runtime.GOARCH; platform {
336 case "darwin/amd64":
337 case "linux/amd64":
338 case "linux/arm64":
339 case "linux/loong64":
340 case "linux/ppc64":
341 case "linux/ppc64le":
342 default:
343 t.Skipf("not yet supported on %s", platform)
344 }
345 if asan.Enabled || msan.Enabled {
346 t.Skip("skipping test on ASAN/MSAN: triggers SIGSEGV in sanitizer runtime")
347 }
348 if runtime.GOOS == "freebsd" && race.Enabled {
349 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
350 }
351 got := runTestProg(t, "testprogcgo", "CrashTraceback")
352 for i := 1; i <= 3; i++ {
353 if !strings.Contains(got, fmt.Sprintf("cgo symbolizer:%d", i)) {
354 t.Errorf("missing cgo symbolizer:%d in %s", i, got)
355 }
356 }
357 }
358
359 func TestCgoCrashTracebackGo(t *testing.T) {
360 t.Parallel()
361 switch platform := runtime.GOOS + "/" + runtime.GOARCH; platform {
362 case "darwin/amd64":
363 case "linux/amd64":
364 case "linux/arm64":
365 case "linux/loong64":
366 case "linux/ppc64":
367 case "linux/ppc64le":
368 default:
369 t.Skipf("not yet supported on %s", platform)
370 }
371 if runtime.GOOS == "freebsd" && race.Enabled {
372 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
373 }
374 got := runTestProg(t, "testprogcgo", "CrashTracebackGo")
375 for i := 1; i <= 3; i++ {
376 want := fmt.Sprintf("main.h%d", i)
377 if !strings.Contains(got, want) {
378 t.Errorf("missing %s", want)
379 }
380 }
381 }
382
383 func TestCgoTracebackContext(t *testing.T) {
384 t.Parallel()
385 if runtime.GOOS == "freebsd" && race.Enabled {
386 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
387 }
388 got := runTestProg(t, "testprogcgo", "TracebackContext")
389 want := "OK\n"
390 if got != want {
391 t.Errorf("expected %q got %v", want, got)
392 }
393 }
394
395 func TestCgoTracebackContextPreemption(t *testing.T) {
396 t.Parallel()
397 if runtime.GOOS == "freebsd" && race.Enabled {
398 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
399 }
400 got := runTestProg(t, "testprogcgo", "TracebackContextPreemption")
401 want := "OK\n"
402 if got != want {
403 t.Errorf("expected %q got %v", want, got)
404 }
405 }
406
407 func TestCgoTracebackContextProfile(t *testing.T) {
408 t.Parallel()
409 if runtime.GOOS == "freebsd" && race.Enabled {
410 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
411 }
412 got := runTestProg(t, "testprogcgo", "TracebackContextProfile")
413 want := "OK\n"
414 if got != want {
415 t.Errorf("expected %q got %v", want, got)
416 }
417 }
418
419 func testCgoPprof(t *testing.T, buildArg, runArg, top, bottom string) {
420 t.Parallel()
421 if runtime.GOOS != "linux" || (runtime.GOARCH != "amd64" && runtime.GOARCH != "ppc64" && runtime.GOARCH != "ppc64le" && runtime.GOARCH != "arm64" && runtime.GOARCH != "loong64") {
422 t.Skipf("not yet supported on %s/%s", runtime.GOOS, runtime.GOARCH)
423 }
424 if runtime.GOOS == "freebsd" && race.Enabled {
425 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
426 }
427 testenv.MustHaveGoRun(t)
428
429 var args []string
430 if buildArg != "" {
431 args = append(args, buildArg)
432 }
433 exe, err := buildTestProg(t, "testprogcgo", args...)
434 if err != nil {
435 t.Fatal(err)
436 }
437
438 cmd := testenv.CleanCmdEnv(exec.Command(exe, runArg))
439 got, err := cmd.CombinedOutput()
440 if err != nil {
441 if testenv.Builder() == "linux-amd64-alpine" {
442
443 t.Skipf("Skipping failing test on Alpine (golang.org/issue/18243). Ignoring error: %v", err)
444 }
445 t.Fatalf("%s\n\n%v", got, err)
446 }
447 fn := strings.TrimSpace(string(got))
448 defer os.Remove(fn)
449
450 for try := 0; try < 2; try++ {
451 cmd := testenv.CleanCmdEnv(exec.Command(testenv.GoToolPath(t), "tool", "pprof", "-tagignore=ignore", "-traces"))
452
453 if try == 0 {
454 cmd.Args = append(cmd.Args, exe, fn)
455 } else {
456 cmd.Args = append(cmd.Args, fn)
457 }
458
459 found := false
460 for i, e := range cmd.Env {
461 if strings.HasPrefix(e, "PPROF_TMPDIR=") {
462 cmd.Env[i] = "PPROF_TMPDIR=" + os.TempDir()
463 found = true
464 break
465 }
466 }
467 if !found {
468 cmd.Env = append(cmd.Env, "PPROF_TMPDIR="+os.TempDir())
469 }
470
471 out, err := cmd.CombinedOutput()
472 t.Logf("%s:\n%s", cmd.Args, out)
473 if err != nil {
474 t.Error(err)
475 continue
476 }
477
478 trace := findTrace(string(out), top)
479 if len(trace) == 0 {
480 t.Errorf("%s traceback missing.", top)
481 continue
482 }
483 if trace[len(trace)-1] != bottom {
484 t.Errorf("invalid traceback origin: got=%v; want=[%s ... %s]", trace, top, bottom)
485 }
486 }
487 }
488
489 func TestCgoPprof(t *testing.T) {
490 testCgoPprof(t, "", "CgoPprof", "cpuHog", "runtime.main")
491 }
492
493 func TestCgoPprofPIE(t *testing.T) {
494 if race.Enabled {
495 t.Skip("skipping test: -race + PIE not supported")
496 }
497 testCgoPprof(t, "-buildmode=pie", "CgoPprof", "cpuHog", "runtime.main")
498 }
499
500 func TestCgoPprofThread(t *testing.T) {
501 testCgoPprof(t, "", "CgoPprofThread", "cpuHogThread", "cpuHogThread2")
502 }
503
504 func TestCgoPprofThreadNoTraceback(t *testing.T) {
505 testCgoPprof(t, "", "CgoPprofThreadNoTraceback", "cpuHogThread", "runtime._ExternalCode")
506 }
507
508 func TestRaceProf(t *testing.T) {
509 if !race.Enabled {
510 t.Skip("skipping: race detector not enabled")
511 }
512 if runtime.GOOS == "windows" {
513 t.Skipf("skipping: test requires pthread support")
514
515 }
516 if runtime.GOOS == "freebsd" && race.Enabled {
517 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
518 }
519
520 testenv.MustHaveGoRun(t)
521
522 exe, err := buildTestProg(t, "testprogcgo")
523 if err != nil {
524 t.Fatal(err)
525 }
526
527 got, err := testenv.CleanCmdEnv(exec.Command(exe, "CgoRaceprof")).CombinedOutput()
528 if err != nil {
529 t.Fatal(err)
530 }
531 want := "OK\n"
532 if string(got) != want {
533 t.Errorf("expected %q got %s", want, got)
534 }
535 }
536
537 func TestRaceSignal(t *testing.T) {
538 if !race.Enabled {
539 t.Skip("skipping: race detector not enabled")
540 }
541 if runtime.GOOS == "windows" {
542 t.Skipf("skipping: test requires pthread support")
543
544 }
545 if runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
546 testenv.SkipFlaky(t, 60316)
547 }
548 if runtime.GOOS == "freebsd" && race.Enabled {
549 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
550 }
551
552 t.Parallel()
553
554 testenv.MustHaveGoRun(t)
555
556 exe, err := buildTestProg(t, "testprogcgo")
557 if err != nil {
558 t.Fatal(err)
559 }
560
561 got, err := testenv.CleanCmdEnv(testenv.Command(t, exe, "CgoRaceSignal")).CombinedOutput()
562 if err != nil {
563 t.Logf("%s\n", got)
564 t.Fatal(err)
565 }
566 want := "OK\n"
567 if string(got) != want {
568 t.Errorf("expected %q got %s", want, got)
569 }
570 }
571
572 func TestCgoNumGoroutine(t *testing.T) {
573 switch runtime.GOOS {
574 case "windows", "plan9":
575 t.Skipf("skipping numgoroutine test on %s", runtime.GOOS)
576 }
577 if runtime.GOOS == "freebsd" && race.Enabled {
578 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
579 }
580 t.Parallel()
581 got := runTestProg(t, "testprogcgo", "NumGoroutine")
582 want := "OK\n"
583 if got != want {
584 t.Errorf("expected %q got %v", want, got)
585 }
586 }
587
588 func TestCatchPanic(t *testing.T) {
589 t.Parallel()
590 switch runtime.GOOS {
591 case "plan9", "windows":
592 t.Skipf("no signals on %s", runtime.GOOS)
593 case "darwin":
594 if runtime.GOARCH == "amd64" {
595 t.Skipf("crash() on darwin/amd64 doesn't raise SIGABRT")
596 }
597 }
598 if runtime.GOOS == "freebsd" && race.Enabled {
599 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
600 }
601
602 testenv.MustHaveGoRun(t)
603
604 exe, err := buildTestProg(t, "testprogcgo")
605 if err != nil {
606 t.Fatal(err)
607 }
608
609 for _, early := range []bool{true, false} {
610 cmd := testenv.CleanCmdEnv(exec.Command(exe, "CgoCatchPanic"))
611
612 cmd.Env = append(cmd.Env, "GOTRACEBACK=crash")
613 if early {
614
615 cmd.Env = append(cmd.Env, "CGOCATCHPANIC_EARLY_HANDLER=1")
616 }
617 if out, err := cmd.CombinedOutput(); err != nil {
618 t.Errorf("testprogcgo CgoCatchPanic failed: %v\n%s", err, out)
619 }
620 }
621 }
622
623 func TestCgoLockOSThreadExit(t *testing.T) {
624 switch runtime.GOOS {
625 case "plan9", "windows":
626 t.Skipf("no pthreads on %s", runtime.GOOS)
627 }
628 if runtime.GOOS == "freebsd" && race.Enabled {
629 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
630 }
631 t.Parallel()
632 testLockOSThreadExit(t, "testprogcgo")
633 }
634
635 func TestWindowsStackMemoryCgo(t *testing.T) {
636 if runtime.GOOS != "windows" {
637 t.Skip("skipping windows specific test")
638 }
639 if race.Enabled {
640 t.Skip("skipping test: race mode uses more stack memory")
641 }
642 testenv.SkipFlaky(t, 22575)
643 o := runTestProg(t, "testprogcgo", "StackMemory")
644 stackUsage, err := strconv.Atoi(o)
645 if err != nil {
646 t.Fatalf("Failed to read stack usage: %v", err)
647 }
648 if expected, got := 100<<10, stackUsage; got > expected {
649 t.Fatalf("expected < %d bytes of memory per thread, got %d", expected, got)
650 }
651 }
652
653 func TestSigStackSwapping(t *testing.T) {
654 switch runtime.GOOS {
655 case "plan9", "windows":
656 t.Skipf("no sigaltstack on %s", runtime.GOOS)
657 }
658 if runtime.GOOS == "freebsd" && race.Enabled {
659 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
660 }
661 t.Parallel()
662 got := runTestProg(t, "testprogcgo", "SigStack")
663 want := "OK\n"
664 if got != want {
665 t.Errorf("expected %q got %v", want, got)
666 }
667 }
668
669 func TestCgoTracebackSigpanic(t *testing.T) {
670
671
672 if runtime.GOOS == "windows" {
673
674
675
676 t.Skip("no sigpanic in C on windows")
677 }
678 if asan.Enabled || msan.Enabled {
679 t.Skip("skipping test on ASAN/MSAN: triggers SIGSEGV in sanitizer runtime")
680 }
681 if runtime.GOOS == "freebsd" && race.Enabled {
682 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
683 }
684 if runtime.GOOS == "ios" {
685 testenv.SkipFlaky(t, 59912)
686 }
687 t.Parallel()
688 got := runTestProg(t, "testprogcgo", "TracebackSigpanic")
689 t.Log(got)
690
691 want := "main.TracebackSigpanic"
692 if !strings.Contains(got, want) {
693 if runtime.GOOS == "android" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") {
694 testenv.SkipFlaky(t, 58794)
695 }
696 t.Errorf("did not see %q in output", want)
697 }
698
699 nowant := "runtime.sigpanic"
700 if strings.Contains(got, nowant) {
701 t.Errorf("unexpectedly saw %q in output", nowant)
702 }
703
704 nowant = "runtime: "
705 if strings.Contains(got, nowant) {
706 t.Errorf("unexpectedly saw %q in output", nowant)
707 }
708 }
709
710 func TestCgoPanicCallback(t *testing.T) {
711 if runtime.GOOS == "freebsd" && race.Enabled {
712 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
713 }
714 t.Parallel()
715 got := runTestProg(t, "testprogcgo", "PanicCallback")
716 t.Log(got)
717 want := "panic: runtime error: invalid memory address or nil pointer dereference"
718 if !strings.Contains(got, want) {
719 t.Errorf("did not see %q in output", want)
720 }
721 want = "panic_callback"
722 if !strings.Contains(got, want) {
723 t.Errorf("did not see %q in output", want)
724 }
725 want = "PanicCallback"
726 if !strings.Contains(got, want) {
727 t.Errorf("did not see %q in output", want)
728 }
729
730 nowant := "runtime: "
731 if strings.Contains(got, nowant) {
732 t.Errorf("did not see %q in output", want)
733 }
734 }
735
736
737
738
739
740 func TestBigStackCallbackCgo(t *testing.T) {
741 if runtime.GOOS != "windows" {
742 t.Skip("skipping windows specific test")
743 }
744 t.Parallel()
745 got := runTestProg(t, "testprogcgo", "BigStack")
746 want := "OK\n"
747 if got != want {
748 t.Errorf("expected %q got %v", want, got)
749 }
750 }
751
752 func nextTrace(lines []string) ([]string, []string) {
753 var trace []string
754 for n, line := range lines {
755 if strings.HasPrefix(line, "---") {
756 return trace, lines[n+1:]
757 }
758 fields := strings.Fields(strings.TrimSpace(line))
759 if len(fields) == 0 {
760 continue
761 }
762
763 trace = append(trace, fields[len(fields)-1])
764 }
765 return nil, nil
766 }
767
768 func findTrace(text, top string) []string {
769 lines := strings.Split(text, "\n")
770 _, lines = nextTrace(lines)
771 for len(lines) > 0 {
772 var t []string
773 t, lines = nextTrace(lines)
774 if len(t) == 0 {
775 continue
776 }
777 if t[0] == top {
778 return t
779 }
780 }
781 return nil
782 }
783
784 func TestSegv(t *testing.T) {
785 switch runtime.GOOS {
786 case "plan9", "windows":
787 t.Skipf("no signals on %s", runtime.GOOS)
788 }
789 if race.Enabled || asan.Enabled || msan.Enabled {
790 t.Skip("skipping test on race/ASAN/MSAN: triggers SIGSEGV in sanitizer runtime")
791 }
792
793 for _, test := range []string{"Segv", "SegvInCgo", "TgkillSegv", "TgkillSegvInCgo"} {
794
795 if runtime.GOOS != "linux" && strings.HasPrefix(test, "Tgkill") {
796 continue
797 }
798
799 t.Run(test, func(t *testing.T) {
800 if test == "SegvInCgo" && runtime.GOOS == "ios" {
801 testenv.SkipFlaky(t, 59947)
802 }
803 if strings.HasSuffix(test, "InCgo") && runtime.GOOS == "freebsd" && race.Enabled {
804 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
805 }
806
807 t.Parallel()
808 prog := "testprog"
809 if strings.HasSuffix(test, "InCgo") {
810 prog = "testprogcgo"
811 }
812 got := runTestProg(t, prog, test)
813 t.Log(got)
814 want := "SIGSEGV"
815 if !strings.Contains(got, want) {
816 if runtime.GOOS == "darwin" && runtime.GOARCH == "amd64" && strings.Contains(got, "fatal: morestack on g0") {
817 testenv.SkipFlaky(t, 39457)
818 }
819 t.Errorf("did not see %q in output", want)
820 }
821
822
823 switch runtime.GOOS {
824 case "darwin", "ios", "illumos", "solaris":
825
826 testenv.SkipFlaky(t, 49182)
827 case "linux":
828 if runtime.GOARCH == "386" {
829
830
831 testenv.SkipFlaky(t, 50504)
832 }
833 }
834 if test == "SegvInCgo" && strings.Contains(got, "unknown pc") {
835 testenv.SkipFlaky(t, 50979)
836 }
837
838 for _, nowant := range []string{"fatal error: ", "runtime: "} {
839 if strings.Contains(got, nowant) {
840 if runtime.GOOS == "darwin" && strings.Contains(got, "0xb01dfacedebac1e") {
841
842 t.Skip("skipping due to Darwin handling of malformed addresses")
843 }
844 t.Errorf("unexpectedly saw %q in output", nowant)
845 }
846 }
847 })
848 }
849 }
850
851 func TestAbortInCgo(t *testing.T) {
852 switch runtime.GOOS {
853 case "plan9", "windows":
854
855
856 t.Skipf("no signals on %s", runtime.GOOS)
857 }
858 if runtime.GOOS == "freebsd" && race.Enabled {
859 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
860 }
861
862 t.Parallel()
863 got := runTestProg(t, "testprogcgo", "Abort")
864 t.Log(got)
865 want := "SIGABRT"
866 if !strings.Contains(got, want) {
867 t.Errorf("did not see %q in output", want)
868 }
869
870 nowant := "runtime: "
871 if strings.Contains(got, nowant) {
872 t.Errorf("did not see %q in output", want)
873 }
874 }
875
876
877
878 func TestEINTR(t *testing.T) {
879 switch runtime.GOOS {
880 case "plan9", "windows":
881 t.Skipf("no EINTR on %s", runtime.GOOS)
882 }
883 if runtime.GOOS == "freebsd" && race.Enabled {
884 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
885 }
886
887 t.Parallel()
888 output := runTestProg(t, "testprogcgo", "EINTR")
889 want := "OK\n"
890 if output != want {
891 t.Fatalf("want %s, got %s\n", want, output)
892 }
893 }
894
895
896 func TestNeedmDeadlock(t *testing.T) {
897 switch runtime.GOOS {
898 case "plan9", "windows":
899 t.Skipf("no signals on %s", runtime.GOOS)
900 }
901 if runtime.GOOS == "freebsd" && race.Enabled {
902 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
903 }
904 output := runTestProg(t, "testprogcgo", "NeedmDeadlock")
905 want := "OK\n"
906 if output != want {
907 t.Fatalf("want %s, got %s\n", want, output)
908 }
909 }
910
911 func TestCgoNoCallback(t *testing.T) {
912 if runtime.GOOS == "freebsd" && race.Enabled {
913 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
914 }
915 got := runTestProg(t, "testprogcgo", "CgoNoCallback")
916 want := "function marked with #cgo nocallback called back into Go"
917 if !strings.Contains(got, want) {
918 t.Fatalf("did not see %q in output:\n%s", want, got)
919 }
920 }
921
922 func TestCgoNoEscape(t *testing.T) {
923 if asan.Enabled {
924 t.Skip("skipping test: ASAN forces extra heap allocations")
925 }
926 if runtime.GOOS == "freebsd" && race.Enabled {
927 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
928 }
929 got := runTestProg(t, "testprogcgo", "CgoNoEscape")
930 want := "OK\n"
931 if got != want {
932 t.Fatalf("want %s, got %s\n", want, got)
933 }
934 }
935
936
937 func TestCgoEscapeWithMultiplePointers(t *testing.T) {
938 if runtime.GOOS == "freebsd" && race.Enabled {
939 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
940 }
941 got := runTestProg(t, "testprogcgo", "CgoEscapeWithMultiplePointers")
942 want := "OK\n"
943 if got != want {
944 t.Fatalf("output is %s; want %s", got, want)
945 }
946 }
947
948 func TestCgoTracebackGoroutineProfile(t *testing.T) {
949 if runtime.GOOS == "freebsd" && race.Enabled {
950 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
951 }
952 output := runTestProg(t, "testprogcgo", "GoroutineProfile")
953 want := "OK\n"
954 if output != want {
955 t.Fatalf("want %s, got %s\n", want, output)
956 }
957 }
958
959 func TestCgoSigfwd(t *testing.T) {
960 t.Parallel()
961 if !goos.IsUnix {
962 t.Skipf("no signals on %s", runtime.GOOS)
963 }
964 if runtime.GOOS == "freebsd" && race.Enabled {
965 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
966 }
967
968 got := runTestProg(t, "testprogcgo", "CgoSigfwd", "GO_TEST_CGOSIGFWD=1")
969 if want := "OK\n"; got != want {
970 t.Fatalf("expected %q, but got:\n%s", want, got)
971 }
972 }
973
974 func TestDestructorCallback(t *testing.T) {
975 if runtime.GOOS == "freebsd" && race.Enabled {
976 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
977 }
978 t.Parallel()
979 got := runTestProg(t, "testprogcgo", "DestructorCallback")
980 if want := "OK\n"; got != want {
981 t.Errorf("expected %q, but got:\n%s", want, got)
982 }
983 }
984
985 func TestEnsureBindM(t *testing.T) {
986 t.Parallel()
987 switch runtime.GOOS {
988 case "windows", "plan9":
989 t.Skipf("skipping bindm test on %s", runtime.GOOS)
990 }
991 if runtime.GOOS == "freebsd" && race.Enabled {
992 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
993 }
994 got := runTestProg(t, "testprogcgo", "EnsureBindM")
995 want := "OK\n"
996 if got != want {
997 t.Errorf("expected %q, got %v", want, got)
998 }
999 }
1000
1001 func TestStackSwitchCallback(t *testing.T) {
1002 t.Parallel()
1003 switch runtime.GOOS {
1004 case "windows", "plan9", "android", "ios", "openbsd":
1005 t.Skipf("skipping test on %s", runtime.GOOS)
1006 }
1007 if asan.Enabled {
1008
1009 t.Skip("skipping test on ASAN because ASAN doesn't fully support makecontext/swapcontext functions")
1010 }
1011 if runtime.GOOS == "freebsd" && race.Enabled {
1012 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
1013 }
1014 got := runTestProg(t, "testprogcgo", "StackSwitchCallback")
1015 skip := "SKIP\n"
1016 if got == skip {
1017 t.Skip("skipping on musl/bionic libc")
1018 }
1019 want := "OK\n"
1020 if got != want {
1021 t.Errorf("expected %q, got %v", want, got)
1022 }
1023 }
1024
1025 func TestCgoToGoCallGoexit(t *testing.T) {
1026 if runtime.GOOS == "plan9" || runtime.GOOS == "windows" {
1027 t.Skipf("no pthreads on %s", runtime.GOOS)
1028 }
1029 if runtime.GOOS == "freebsd" && race.Enabled {
1030 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
1031 }
1032 output := runTestProg(t, "testprogcgo", "CgoToGoCallGoexit")
1033 if !strings.Contains(output, "runtime.Goexit called in a thread that was not created by the Go runtime") {
1034 t.Fatalf("output should contain %s, got %s", "runtime.Goexit called in a thread that was not created by the Go runtime", output)
1035 }
1036 }
1037
View as plain text