github.com/ice-blockchain/go/src@v0.0.0-20240403114104-1564d284e521/runtime/crash_cgo_test.go (about) 1 // 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 //go:build cgo 6 7 package runtime_test 8 9 import ( 10 "fmt" 11 "internal/goexperiment" 12 "internal/goos" 13 "internal/platform" 14 "internal/testenv" 15 "os" 16 "os/exec" 17 "runtime" 18 "strconv" 19 "strings" 20 "testing" 21 "time" 22 ) 23 24 func TestCgoCrashHandler(t *testing.T) { 25 t.Parallel() 26 testCrashHandler(t, true) 27 } 28 29 func TestCgoSignalDeadlock(t *testing.T) { 30 // Don't call t.Parallel, since too much work going on at the 31 // same time can cause the testprogcgo code to overrun its 32 // timeouts (issue #18598). 33 34 if testing.Short() && runtime.GOOS == "windows" { 35 t.Skip("Skipping in short mode") // takes up to 64 seconds 36 } 37 got := runTestProg(t, "testprogcgo", "CgoSignalDeadlock") 38 want := "OK\n" 39 if got != want { 40 t.Fatalf("expected %q, but got:\n%s", want, got) 41 } 42 } 43 44 func TestCgoTraceback(t *testing.T) { 45 t.Parallel() 46 got := runTestProg(t, "testprogcgo", "CgoTraceback") 47 want := "OK\n" 48 if got != want { 49 t.Fatalf("expected %q, but got:\n%s", want, got) 50 } 51 } 52 53 func TestCgoCallbackGC(t *testing.T) { 54 t.Parallel() 55 switch runtime.GOOS { 56 case "plan9", "windows": 57 t.Skipf("no pthreads on %s", runtime.GOOS) 58 } 59 if testing.Short() { 60 switch { 61 case runtime.GOOS == "dragonfly": 62 t.Skip("see golang.org/issue/11990") 63 case runtime.GOOS == "linux" && runtime.GOARCH == "arm": 64 t.Skip("too slow for arm builders") 65 case runtime.GOOS == "linux" && (runtime.GOARCH == "mips64" || runtime.GOARCH == "mips64le"): 66 t.Skip("too slow for mips64x builders") 67 } 68 } 69 if testenv.Builder() == "darwin-amd64-10_14" { 70 // TODO(#23011): When the 10.14 builders are gone, remove this skip. 71 t.Skip("skipping due to platform bug on macOS 10.14; see https://golang.org/issue/43926") 72 } 73 got := runTestProg(t, "testprogcgo", "CgoCallbackGC") 74 want := "OK\n" 75 if got != want { 76 t.Fatalf("expected %q, but got:\n%s", want, got) 77 } 78 } 79 80 func TestCgoExternalThreadPanic(t *testing.T) { 81 t.Parallel() 82 if runtime.GOOS == "plan9" { 83 t.Skipf("no pthreads on %s", runtime.GOOS) 84 } 85 got := runTestProg(t, "testprogcgo", "CgoExternalThreadPanic") 86 want := "panic: BOOM" 87 if !strings.Contains(got, want) { 88 t.Fatalf("want failure containing %q. output:\n%s\n", want, got) 89 } 90 } 91 92 func TestCgoExternalThreadSIGPROF(t *testing.T) { 93 t.Parallel() 94 // issue 9456. 95 switch runtime.GOOS { 96 case "plan9", "windows": 97 t.Skipf("no pthreads on %s", runtime.GOOS) 98 } 99 100 got := runTestProg(t, "testprogcgo", "CgoExternalThreadSIGPROF", "GO_START_SIGPROF_THREAD=1") 101 if want := "OK\n"; got != want { 102 t.Fatalf("expected %q, but got:\n%s", want, got) 103 } 104 } 105 106 func TestCgoExternalThreadSignal(t *testing.T) { 107 t.Parallel() 108 // issue 10139 109 switch runtime.GOOS { 110 case "plan9", "windows": 111 t.Skipf("no pthreads on %s", runtime.GOOS) 112 } 113 114 got := runTestProg(t, "testprogcgo", "CgoExternalThreadSignal") 115 if want := "OK\n"; got != want { 116 if runtime.GOOS == "ios" && strings.Contains(got, "C signal did not crash as expected") { 117 testenv.SkipFlaky(t, 59913) 118 } 119 t.Fatalf("expected %q, but got:\n%s", want, got) 120 } 121 } 122 123 func TestCgoDLLImports(t *testing.T) { 124 // test issue 9356 125 if runtime.GOOS != "windows" { 126 t.Skip("skipping windows specific test") 127 } 128 got := runTestProg(t, "testprogcgo", "CgoDLLImportsMain") 129 want := "OK\n" 130 if got != want { 131 t.Fatalf("expected %q, but got %v", want, got) 132 } 133 } 134 135 func TestCgoExecSignalMask(t *testing.T) { 136 t.Parallel() 137 // Test issue 13164. 138 switch runtime.GOOS { 139 case "windows", "plan9": 140 t.Skipf("skipping signal mask test on %s", runtime.GOOS) 141 } 142 got := runTestProg(t, "testprogcgo", "CgoExecSignalMask", "GOTRACEBACK=system") 143 want := "OK\n" 144 if got != want { 145 t.Errorf("expected %q, got %v", want, got) 146 } 147 } 148 149 func TestEnsureDropM(t *testing.T) { 150 t.Parallel() 151 // Test for issue 13881. 152 switch runtime.GOOS { 153 case "windows", "plan9": 154 t.Skipf("skipping dropm test on %s", runtime.GOOS) 155 } 156 got := runTestProg(t, "testprogcgo", "EnsureDropM") 157 want := "OK\n" 158 if got != want { 159 t.Errorf("expected %q, got %v", want, got) 160 } 161 } 162 163 // Test for issue 14387. 164 // Test that the program that doesn't need any cgo pointer checking 165 // takes about the same amount of time with it as without it. 166 func TestCgoCheckBytes(t *testing.T) { 167 t.Parallel() 168 // Make sure we don't count the build time as part of the run time. 169 testenv.MustHaveGoBuild(t) 170 exe, err := buildTestProg(t, "testprogcgo") 171 if err != nil { 172 t.Fatal(err) 173 } 174 175 // Try it 10 times to avoid flakiness. 176 const tries = 10 177 var tot1, tot2 time.Duration 178 for i := 0; i < tries; i++ { 179 cmd := testenv.CleanCmdEnv(exec.Command(exe, "CgoCheckBytes")) 180 cmd.Env = append(cmd.Env, "GODEBUG=cgocheck=0", fmt.Sprintf("GO_CGOCHECKBYTES_TRY=%d", i)) 181 182 start := time.Now() 183 cmd.Run() 184 d1 := time.Since(start) 185 186 cmd = testenv.CleanCmdEnv(exec.Command(exe, "CgoCheckBytes")) 187 cmd.Env = append(cmd.Env, fmt.Sprintf("GO_CGOCHECKBYTES_TRY=%d", i)) 188 189 start = time.Now() 190 cmd.Run() 191 d2 := time.Since(start) 192 193 if d1*20 > d2 { 194 // The slow version (d2) was less than 20 times 195 // slower than the fast version (d1), so OK. 196 return 197 } 198 199 tot1 += d1 200 tot2 += d2 201 } 202 203 t.Errorf("cgo check too slow: got %v, expected at most %v", tot2/tries, (tot1/tries)*20) 204 } 205 206 func TestCgoPanicDeadlock(t *testing.T) { 207 t.Parallel() 208 // test issue 14432 209 got := runTestProg(t, "testprogcgo", "CgoPanicDeadlock") 210 want := "panic: cgo error\n\n" 211 if !strings.HasPrefix(got, want) { 212 t.Fatalf("output does not start with %q:\n%s", want, got) 213 } 214 } 215 216 func TestCgoCCodeSIGPROF(t *testing.T) { 217 t.Parallel() 218 got := runTestProg(t, "testprogcgo", "CgoCCodeSIGPROF") 219 want := "OK\n" 220 if got != want { 221 t.Errorf("expected %q got %v", want, got) 222 } 223 } 224 225 func TestCgoPprofCallback(t *testing.T) { 226 if testing.Short() { 227 t.Skip("skipping in short mode") // takes a full second 228 } 229 switch runtime.GOOS { 230 case "windows", "plan9": 231 t.Skipf("skipping cgo pprof callback test on %s", runtime.GOOS) 232 } 233 got := runTestProg(t, "testprogcgo", "CgoPprofCallback") 234 want := "OK\n" 235 if got != want { 236 t.Errorf("expected %q got %v", want, got) 237 } 238 } 239 240 func TestCgoCrashTraceback(t *testing.T) { 241 t.Parallel() 242 switch platform := runtime.GOOS + "/" + runtime.GOARCH; platform { 243 case "darwin/amd64": 244 case "linux/amd64": 245 case "linux/arm64": 246 case "linux/ppc64le": 247 default: 248 t.Skipf("not yet supported on %s", platform) 249 } 250 got := runTestProg(t, "testprogcgo", "CrashTraceback") 251 for i := 1; i <= 3; i++ { 252 if !strings.Contains(got, fmt.Sprintf("cgo symbolizer:%d", i)) { 253 t.Errorf("missing cgo symbolizer:%d", i) 254 } 255 } 256 } 257 258 func TestCgoCrashTracebackGo(t *testing.T) { 259 t.Parallel() 260 switch platform := runtime.GOOS + "/" + runtime.GOARCH; platform { 261 case "darwin/amd64": 262 case "linux/amd64": 263 case "linux/arm64": 264 case "linux/ppc64le": 265 default: 266 t.Skipf("not yet supported on %s", platform) 267 } 268 got := runTestProg(t, "testprogcgo", "CrashTracebackGo") 269 for i := 1; i <= 3; i++ { 270 want := fmt.Sprintf("main.h%d", i) 271 if !strings.Contains(got, want) { 272 t.Errorf("missing %s", want) 273 } 274 } 275 } 276 277 func TestCgoTracebackContext(t *testing.T) { 278 t.Parallel() 279 got := runTestProg(t, "testprogcgo", "TracebackContext") 280 want := "OK\n" 281 if got != want { 282 t.Errorf("expected %q got %v", want, got) 283 } 284 } 285 286 func TestCgoTracebackContextPreemption(t *testing.T) { 287 t.Parallel() 288 got := runTestProg(t, "testprogcgo", "TracebackContextPreemption") 289 want := "OK\n" 290 if got != want { 291 t.Errorf("expected %q got %v", want, got) 292 } 293 } 294 295 func testCgoPprof(t *testing.T, buildArg, runArg, top, bottom string) { 296 t.Parallel() 297 if runtime.GOOS != "linux" || (runtime.GOARCH != "amd64" && runtime.GOARCH != "ppc64le" && runtime.GOARCH != "arm64") { 298 t.Skipf("not yet supported on %s/%s", runtime.GOOS, runtime.GOARCH) 299 } 300 testenv.MustHaveGoRun(t) 301 302 exe, err := buildTestProg(t, "testprogcgo", buildArg) 303 if err != nil { 304 t.Fatal(err) 305 } 306 307 cmd := testenv.CleanCmdEnv(exec.Command(exe, runArg)) 308 got, err := cmd.CombinedOutput() 309 if err != nil { 310 if testenv.Builder() == "linux-amd64-alpine" { 311 // See Issue 18243 and Issue 19938. 312 t.Skipf("Skipping failing test on Alpine (golang.org/issue/18243). Ignoring error: %v", err) 313 } 314 t.Fatalf("%s\n\n%v", got, err) 315 } 316 fn := strings.TrimSpace(string(got)) 317 defer os.Remove(fn) 318 319 for try := 0; try < 2; try++ { 320 cmd := testenv.CleanCmdEnv(exec.Command(testenv.GoToolPath(t), "tool", "pprof", "-tagignore=ignore", "-traces")) 321 // Check that pprof works both with and without explicit executable on command line. 322 if try == 0 { 323 cmd.Args = append(cmd.Args, exe, fn) 324 } else { 325 cmd.Args = append(cmd.Args, fn) 326 } 327 328 found := false 329 for i, e := range cmd.Env { 330 if strings.HasPrefix(e, "PPROF_TMPDIR=") { 331 cmd.Env[i] = "PPROF_TMPDIR=" + os.TempDir() 332 found = true 333 break 334 } 335 } 336 if !found { 337 cmd.Env = append(cmd.Env, "PPROF_TMPDIR="+os.TempDir()) 338 } 339 340 out, err := cmd.CombinedOutput() 341 t.Logf("%s:\n%s", cmd.Args, out) 342 if err != nil { 343 t.Error(err) 344 continue 345 } 346 347 trace := findTrace(string(out), top) 348 if len(trace) == 0 { 349 t.Errorf("%s traceback missing.", top) 350 continue 351 } 352 if trace[len(trace)-1] != bottom { 353 t.Errorf("invalid traceback origin: got=%v; want=[%s ... %s]", trace, top, bottom) 354 } 355 } 356 } 357 358 func TestCgoPprof(t *testing.T) { 359 testCgoPprof(t, "", "CgoPprof", "cpuHog", "runtime.main") 360 } 361 362 func TestCgoPprofPIE(t *testing.T) { 363 testCgoPprof(t, "-buildmode=pie", "CgoPprof", "cpuHog", "runtime.main") 364 } 365 366 func TestCgoPprofThread(t *testing.T) { 367 testCgoPprof(t, "", "CgoPprofThread", "cpuHogThread", "cpuHogThread2") 368 } 369 370 func TestCgoPprofThreadNoTraceback(t *testing.T) { 371 testCgoPprof(t, "", "CgoPprofThreadNoTraceback", "cpuHogThread", "runtime._ExternalCode") 372 } 373 374 func TestRaceProf(t *testing.T) { 375 if !platform.RaceDetectorSupported(runtime.GOOS, runtime.GOARCH) { 376 t.Skipf("skipping on %s/%s because race detector not supported", runtime.GOOS, runtime.GOARCH) 377 } 378 if runtime.GOOS == "windows" { 379 t.Skipf("skipping: test requires pthread support") 380 // TODO: Can this test be rewritten to use the C11 thread API instead? 381 } 382 383 testenv.MustHaveGoRun(t) 384 385 // This test requires building various packages with -race, so 386 // it's somewhat slow. 387 if testing.Short() { 388 t.Skip("skipping test in -short mode") 389 } 390 391 exe, err := buildTestProg(t, "testprogcgo", "-race") 392 if err != nil { 393 t.Fatal(err) 394 } 395 396 got, err := testenv.CleanCmdEnv(exec.Command(exe, "CgoRaceprof")).CombinedOutput() 397 if err != nil { 398 t.Fatal(err) 399 } 400 want := "OK\n" 401 if string(got) != want { 402 t.Errorf("expected %q got %s", want, got) 403 } 404 } 405 406 func TestRaceSignal(t *testing.T) { 407 if !platform.RaceDetectorSupported(runtime.GOOS, runtime.GOARCH) { 408 t.Skipf("skipping on %s/%s because race detector not supported", runtime.GOOS, runtime.GOARCH) 409 } 410 if runtime.GOOS == "windows" { 411 t.Skipf("skipping: test requires pthread support") 412 // TODO: Can this test be rewritten to use the C11 thread API instead? 413 } 414 if runtime.GOOS == "darwin" || runtime.GOOS == "ios" { 415 testenv.SkipFlaky(t, 60316) 416 } 417 418 t.Parallel() 419 420 testenv.MustHaveGoRun(t) 421 422 // This test requires building various packages with -race, so 423 // it's somewhat slow. 424 if testing.Short() { 425 t.Skip("skipping test in -short mode") 426 } 427 428 exe, err := buildTestProg(t, "testprogcgo", "-race") 429 if err != nil { 430 t.Fatal(err) 431 } 432 433 got, err := testenv.CleanCmdEnv(testenv.Command(t, exe, "CgoRaceSignal")).CombinedOutput() 434 if err != nil { 435 t.Logf("%s\n", got) 436 t.Fatal(err) 437 } 438 want := "OK\n" 439 if string(got) != want { 440 t.Errorf("expected %q got %s", want, got) 441 } 442 } 443 444 func TestCgoNumGoroutine(t *testing.T) { 445 switch runtime.GOOS { 446 case "windows", "plan9": 447 t.Skipf("skipping numgoroutine test on %s", runtime.GOOS) 448 } 449 t.Parallel() 450 got := runTestProg(t, "testprogcgo", "NumGoroutine") 451 want := "OK\n" 452 if got != want { 453 t.Errorf("expected %q got %v", want, got) 454 } 455 } 456 457 func TestCatchPanic(t *testing.T) { 458 t.Parallel() 459 switch runtime.GOOS { 460 case "plan9", "windows": 461 t.Skipf("no signals on %s", runtime.GOOS) 462 case "darwin": 463 if runtime.GOARCH == "amd64" { 464 t.Skipf("crash() on darwin/amd64 doesn't raise SIGABRT") 465 } 466 } 467 468 testenv.MustHaveGoRun(t) 469 470 exe, err := buildTestProg(t, "testprogcgo") 471 if err != nil { 472 t.Fatal(err) 473 } 474 475 for _, early := range []bool{true, false} { 476 cmd := testenv.CleanCmdEnv(exec.Command(exe, "CgoCatchPanic")) 477 // Make sure a panic results in a crash. 478 cmd.Env = append(cmd.Env, "GOTRACEBACK=crash") 479 if early { 480 // Tell testprogcgo to install an early signal handler for SIGABRT 481 cmd.Env = append(cmd.Env, "CGOCATCHPANIC_EARLY_HANDLER=1") 482 } 483 if out, err := cmd.CombinedOutput(); err != nil { 484 t.Errorf("testprogcgo CgoCatchPanic failed: %v\n%s", err, out) 485 } 486 } 487 } 488 489 func TestCgoLockOSThreadExit(t *testing.T) { 490 switch runtime.GOOS { 491 case "plan9", "windows": 492 t.Skipf("no pthreads on %s", runtime.GOOS) 493 } 494 t.Parallel() 495 testLockOSThreadExit(t, "testprogcgo") 496 } 497 498 func TestWindowsStackMemoryCgo(t *testing.T) { 499 if runtime.GOOS != "windows" { 500 t.Skip("skipping windows specific test") 501 } 502 testenv.SkipFlaky(t, 22575) 503 o := runTestProg(t, "testprogcgo", "StackMemory") 504 stackUsage, err := strconv.Atoi(o) 505 if err != nil { 506 t.Fatalf("Failed to read stack usage: %v", err) 507 } 508 if expected, got := 100<<10, stackUsage; got > expected { 509 t.Fatalf("expected < %d bytes of memory per thread, got %d", expected, got) 510 } 511 } 512 513 func TestSigStackSwapping(t *testing.T) { 514 switch runtime.GOOS { 515 case "plan9", "windows": 516 t.Skipf("no sigaltstack on %s", runtime.GOOS) 517 } 518 t.Parallel() 519 got := runTestProg(t, "testprogcgo", "SigStack") 520 want := "OK\n" 521 if got != want { 522 t.Errorf("expected %q got %v", want, got) 523 } 524 } 525 526 func TestCgoTracebackSigpanic(t *testing.T) { 527 // Test unwinding over a sigpanic in C code without a C 528 // symbolizer. See issue #23576. 529 if runtime.GOOS == "windows" { 530 // On Windows if we get an exception in C code, we let 531 // the Windows exception handler unwind it, rather 532 // than injecting a sigpanic. 533 t.Skip("no sigpanic in C on windows") 534 } 535 if runtime.GOOS == "ios" { 536 testenv.SkipFlaky(t, 59912) 537 } 538 t.Parallel() 539 got := runTestProg(t, "testprogcgo", "TracebackSigpanic") 540 t.Log(got) 541 // We should see the function that calls the C function. 542 want := "main.TracebackSigpanic" 543 if !strings.Contains(got, want) { 544 if runtime.GOOS == "android" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") { 545 testenv.SkipFlaky(t, 58794) 546 } 547 t.Errorf("did not see %q in output", want) 548 } 549 // We shouldn't inject a sigpanic call. (see issue 57698) 550 nowant := "runtime.sigpanic" 551 if strings.Contains(got, nowant) { 552 t.Errorf("unexpectedly saw %q in output", nowant) 553 } 554 // No runtime errors like "runtime: unexpected return pc". 555 nowant = "runtime: " 556 if strings.Contains(got, nowant) { 557 t.Errorf("unexpectedly saw %q in output", nowant) 558 } 559 } 560 561 func TestCgoPanicCallback(t *testing.T) { 562 t.Parallel() 563 got := runTestProg(t, "testprogcgo", "PanicCallback") 564 t.Log(got) 565 want := "panic: runtime error: invalid memory address or nil pointer dereference" 566 if !strings.Contains(got, want) { 567 t.Errorf("did not see %q in output", want) 568 } 569 want = "panic_callback" 570 if !strings.Contains(got, want) { 571 t.Errorf("did not see %q in output", want) 572 } 573 want = "PanicCallback" 574 if !strings.Contains(got, want) { 575 t.Errorf("did not see %q in output", want) 576 } 577 // No runtime errors like "runtime: unexpected return pc". 578 nowant := "runtime: " 579 if strings.Contains(got, nowant) { 580 t.Errorf("did not see %q in output", want) 581 } 582 } 583 584 // Test that C code called via cgo can use large Windows thread stacks 585 // and call back in to Go without crashing. See issue #20975. 586 // 587 // See also TestBigStackCallbackSyscall. 588 func TestBigStackCallbackCgo(t *testing.T) { 589 if runtime.GOOS != "windows" { 590 t.Skip("skipping windows specific test") 591 } 592 t.Parallel() 593 got := runTestProg(t, "testprogcgo", "BigStack") 594 want := "OK\n" 595 if got != want { 596 t.Errorf("expected %q got %v", want, got) 597 } 598 } 599 600 func nextTrace(lines []string) ([]string, []string) { 601 var trace []string 602 for n, line := range lines { 603 if strings.HasPrefix(line, "---") { 604 return trace, lines[n+1:] 605 } 606 fields := strings.Fields(strings.TrimSpace(line)) 607 if len(fields) == 0 { 608 continue 609 } 610 // Last field contains the function name. 611 trace = append(trace, fields[len(fields)-1]) 612 } 613 return nil, nil 614 } 615 616 func findTrace(text, top string) []string { 617 lines := strings.Split(text, "\n") 618 _, lines = nextTrace(lines) // Skip the header. 619 for len(lines) > 0 { 620 var t []string 621 t, lines = nextTrace(lines) 622 if len(t) == 0 { 623 continue 624 } 625 if t[0] == top { 626 return t 627 } 628 } 629 return nil 630 } 631 632 func TestSegv(t *testing.T) { 633 switch runtime.GOOS { 634 case "plan9", "windows": 635 t.Skipf("no signals on %s", runtime.GOOS) 636 } 637 638 for _, test := range []string{"Segv", "SegvInCgo", "TgkillSegv", "TgkillSegvInCgo"} { 639 test := test 640 641 // The tgkill variants only run on Linux. 642 if runtime.GOOS != "linux" && strings.HasPrefix(test, "Tgkill") { 643 continue 644 } 645 646 t.Run(test, func(t *testing.T) { 647 if test == "SegvInCgo" && runtime.GOOS == "ios" { 648 testenv.SkipFlaky(t, 59947) // Don't even try, in case it times out. 649 } 650 651 t.Parallel() 652 prog := "testprog" 653 if strings.HasSuffix(test, "InCgo") { 654 prog = "testprogcgo" 655 } 656 got := runTestProg(t, prog, test) 657 t.Log(got) 658 want := "SIGSEGV" 659 if !strings.Contains(got, want) { 660 if runtime.GOOS == "darwin" && runtime.GOARCH == "amd64" && strings.Contains(got, "fatal: morestack on g0") { 661 testenv.SkipFlaky(t, 39457) 662 } 663 t.Errorf("did not see %q in output", want) 664 } 665 666 // No runtime errors like "runtime: unknown pc". 667 switch runtime.GOOS { 668 case "darwin", "ios", "illumos", "solaris": 669 // Runtime sometimes throws when generating the traceback. 670 testenv.SkipFlaky(t, 49182) 671 case "linux": 672 if runtime.GOARCH == "386" { 673 // Runtime throws when generating a traceback from 674 // a VDSO call via asmcgocall. 675 testenv.SkipFlaky(t, 50504) 676 } 677 } 678 if test == "SegvInCgo" && strings.Contains(got, "unknown pc") { 679 testenv.SkipFlaky(t, 50979) 680 } 681 682 for _, nowant := range []string{"fatal error: ", "runtime: "} { 683 if strings.Contains(got, nowant) { 684 if runtime.GOOS == "darwin" && strings.Contains(got, "0xb01dfacedebac1e") { 685 // See the comment in signal_darwin_amd64.go. 686 t.Skip("skipping due to Darwin handling of malformed addresses") 687 } 688 t.Errorf("unexpectedly saw %q in output", nowant) 689 } 690 } 691 }) 692 } 693 } 694 695 func TestAbortInCgo(t *testing.T) { 696 switch runtime.GOOS { 697 case "plan9", "windows": 698 // N.B. On Windows, C abort() causes the program to exit 699 // without going through the runtime at all. 700 t.Skipf("no signals on %s", runtime.GOOS) 701 } 702 703 t.Parallel() 704 got := runTestProg(t, "testprogcgo", "Abort") 705 t.Log(got) 706 want := "SIGABRT" 707 if !strings.Contains(got, want) { 708 t.Errorf("did not see %q in output", want) 709 } 710 // No runtime errors like "runtime: unknown pc". 711 nowant := "runtime: " 712 if strings.Contains(got, nowant) { 713 t.Errorf("did not see %q in output", want) 714 } 715 } 716 717 // TestEINTR tests that we handle EINTR correctly. 718 // See issue #20400 and friends. 719 func TestEINTR(t *testing.T) { 720 switch runtime.GOOS { 721 case "plan9", "windows": 722 t.Skipf("no EINTR on %s", runtime.GOOS) 723 case "linux": 724 if runtime.GOARCH == "386" { 725 // On linux-386 the Go signal handler sets 726 // a restorer function that is not preserved 727 // by the C sigaction call in the test, 728 // causing the signal handler to crash when 729 // returning the normal code. The test is not 730 // architecture-specific, so just skip on 386 731 // rather than doing a complicated workaround. 732 t.Skip("skipping on linux-386; C sigaction does not preserve Go restorer") 733 } 734 } 735 736 t.Parallel() 737 output := runTestProg(t, "testprogcgo", "EINTR") 738 want := "OK\n" 739 if output != want { 740 t.Fatalf("want %s, got %s\n", want, output) 741 } 742 } 743 744 // Issue #42207. 745 func TestNeedmDeadlock(t *testing.T) { 746 switch runtime.GOOS { 747 case "plan9", "windows": 748 t.Skipf("no signals on %s", runtime.GOOS) 749 } 750 output := runTestProg(t, "testprogcgo", "NeedmDeadlock") 751 want := "OK\n" 752 if output != want { 753 t.Fatalf("want %s, got %s\n", want, output) 754 } 755 } 756 757 func TestCgoNoCallback(t *testing.T) { 758 t.Skip("TODO(#56378): enable in Go 1.23") 759 got := runTestProg(t, "testprogcgo", "CgoNoCallback") 760 want := "function marked with #cgo nocallback called back into Go" 761 if !strings.Contains(got, want) { 762 t.Fatalf("did not see %q in output:\n%s", want, got) 763 } 764 } 765 766 func TestCgoNoEscape(t *testing.T) { 767 t.Skip("TODO(#56378): enable in Go 1.23") 768 got := runTestProg(t, "testprogcgo", "CgoNoEscape") 769 want := "OK\n" 770 if got != want { 771 t.Fatalf("want %s, got %s\n", want, got) 772 } 773 } 774 775 func TestCgoTracebackGoroutineProfile(t *testing.T) { 776 output := runTestProg(t, "testprogcgo", "GoroutineProfile") 777 want := "OK\n" 778 if output != want { 779 t.Fatalf("want %s, got %s\n", want, output) 780 } 781 } 782 783 func TestCgoTraceParser(t *testing.T) { 784 // Test issue 29707. 785 switch runtime.GOOS { 786 case "plan9", "windows": 787 t.Skipf("no pthreads on %s", runtime.GOOS) 788 } 789 if goexperiment.ExecTracer2 { 790 t.Skip("skipping test that is covered elsewhere for the new execution tracer") 791 } 792 output := runTestProg(t, "testprogcgo", "CgoTraceParser") 793 want := "OK\n" 794 ErrTimeOrder := "ErrTimeOrder\n" 795 if output == ErrTimeOrder { 796 t.Skipf("skipping due to golang.org/issue/16755: %v", output) 797 } else if output != want { 798 t.Fatalf("want %s, got %s\n", want, output) 799 } 800 } 801 802 func TestCgoTraceParserWithOneProc(t *testing.T) { 803 // Test issue 29707. 804 switch runtime.GOOS { 805 case "plan9", "windows": 806 t.Skipf("no pthreads on %s", runtime.GOOS) 807 } 808 if goexperiment.ExecTracer2 { 809 t.Skip("skipping test that is covered elsewhere for the new execution tracer") 810 } 811 output := runTestProg(t, "testprogcgo", "CgoTraceParser", "GOMAXPROCS=1") 812 want := "OK\n" 813 ErrTimeOrder := "ErrTimeOrder\n" 814 if output == ErrTimeOrder { 815 t.Skipf("skipping due to golang.org/issue/16755: %v", output) 816 } else if output != want { 817 t.Fatalf("GOMAXPROCS=1, want %s, got %s\n", want, output) 818 } 819 } 820 821 func TestCgoSigfwd(t *testing.T) { 822 t.Parallel() 823 if !goos.IsUnix { 824 t.Skipf("no signals on %s", runtime.GOOS) 825 } 826 827 got := runTestProg(t, "testprogcgo", "CgoSigfwd", "GO_TEST_CGOSIGFWD=1") 828 if want := "OK\n"; got != want { 829 t.Fatalf("expected %q, but got:\n%s", want, got) 830 } 831 } 832 833 func TestDestructorCallback(t *testing.T) { 834 t.Parallel() 835 got := runTestProg(t, "testprogcgo", "DestructorCallback") 836 if want := "OK\n"; got != want { 837 t.Errorf("expected %q, but got:\n%s", want, got) 838 } 839 } 840 841 func TestDestructorCallbackRace(t *testing.T) { 842 // This test requires building with -race, 843 // so it's somewhat slow. 844 if testing.Short() { 845 t.Skip("skipping test in -short mode") 846 } 847 848 if !platform.RaceDetectorSupported(runtime.GOOS, runtime.GOARCH) { 849 t.Skipf("skipping on %s/%s because race detector not supported", runtime.GOOS, runtime.GOARCH) 850 } 851 852 t.Parallel() 853 854 exe, err := buildTestProg(t, "testprogcgo", "-race") 855 if err != nil { 856 t.Fatal(err) 857 } 858 859 got, err := testenv.CleanCmdEnv(exec.Command(exe, "DestructorCallback")).CombinedOutput() 860 if err != nil { 861 t.Fatal(err) 862 } 863 864 if want := "OK\n"; string(got) != want { 865 t.Errorf("expected %q, but got:\n%s", want, got) 866 } 867 } 868 869 func TestEnsureBindM(t *testing.T) { 870 t.Parallel() 871 switch runtime.GOOS { 872 case "windows", "plan9": 873 t.Skipf("skipping bindm test on %s", runtime.GOOS) 874 } 875 got := runTestProg(t, "testprogcgo", "EnsureBindM") 876 want := "OK\n" 877 if got != want { 878 t.Errorf("expected %q, got %v", want, got) 879 } 880 } 881 882 func TestStackSwitchCallback(t *testing.T) { 883 t.Parallel() 884 switch runtime.GOOS { 885 case "windows", "plan9", "android", "ios", "openbsd": // no getcontext 886 t.Skipf("skipping test on %s", runtime.GOOS) 887 } 888 got := runTestProg(t, "testprogcgo", "StackSwitchCallback") 889 skip := "SKIP\n" 890 if got == skip { 891 t.Skip("skipping on musl/bionic libc") 892 } 893 want := "OK\n" 894 if got != want { 895 t.Errorf("expected %q, got %v", want, got) 896 } 897 }