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