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