...

Source file src/runtime/crash_cgo_test.go

Documentation: runtime

		 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  // +build cgo
		 7  
		 8  package runtime_test
		 9  
		10  import (
		11  	"bytes"
		12  	"fmt"
		13  	"internal/testenv"
		14  	"os"
		15  	"os/exec"
		16  	"runtime"
		17  	"strconv"
		18  	"strings"
		19  	"testing"
		20  	"time"
		21  )
		22  
		23  func TestCgoCrashHandler(t *testing.T) {
		24  	t.Parallel()
		25  	testCrashHandler(t, true)
		26  }
		27  
		28  func TestCgoSignalDeadlock(t *testing.T) {
		29  	// Don't call t.Parallel, since too much work going on at the
		30  	// same time can cause the testprogcgo code to overrun its
		31  	// timeouts (issue #18598).
		32  
		33  	if testing.Short() && runtime.GOOS == "windows" {
		34  		t.Skip("Skipping in short mode") // takes up to 64 seconds
		35  	}
		36  	got := runTestProg(t, "testprogcgo", "CgoSignalDeadlock")
		37  	want := "OK\n"
		38  	if got != want {
		39  		t.Fatalf("expected %q, but got:\n%s", want, got)
		40  	}
		41  }
		42  
		43  func TestCgoTraceback(t *testing.T) {
		44  	t.Parallel()
		45  	got := runTestProg(t, "testprogcgo", "CgoTraceback")
		46  	want := "OK\n"
		47  	if got != want {
		48  		t.Fatalf("expected %q, but got:\n%s", want, got)
		49  	}
		50  }
		51  
		52  func TestCgoCallbackGC(t *testing.T) {
		53  	t.Parallel()
		54  	switch runtime.GOOS {
		55  	case "plan9", "windows":
		56  		t.Skipf("no pthreads on %s", runtime.GOOS)
		57  	}
		58  	if testing.Short() {
		59  		switch {
		60  		case runtime.GOOS == "dragonfly":
		61  			t.Skip("see golang.org/issue/11990")
		62  		case runtime.GOOS == "linux" && runtime.GOARCH == "arm":
		63  			t.Skip("too slow for arm builders")
		64  		case runtime.GOOS == "linux" && (runtime.GOARCH == "mips64" || runtime.GOARCH == "mips64le"):
		65  			t.Skip("too slow for mips64x builders")
		66  		}
		67  	}
		68  	got := runTestProg(t, "testprogcgo", "CgoCallbackGC")
		69  	want := "OK\n"
		70  	if got != want {
		71  		t.Fatalf("expected %q, but got:\n%s", want, got)
		72  	}
		73  }
		74  
		75  func TestCgoExternalThreadPanic(t *testing.T) {
		76  	t.Parallel()
		77  	if runtime.GOOS == "plan9" {
		78  		t.Skipf("no pthreads on %s", runtime.GOOS)
		79  	}
		80  	got := runTestProg(t, "testprogcgo", "CgoExternalThreadPanic")
		81  	want := "panic: BOOM"
		82  	if !strings.Contains(got, want) {
		83  		t.Fatalf("want failure containing %q. output:\n%s\n", want, got)
		84  	}
		85  }
		86  
		87  func TestCgoExternalThreadSIGPROF(t *testing.T) {
		88  	t.Parallel()
		89  	// issue 9456.
		90  	switch runtime.GOOS {
		91  	case "plan9", "windows":
		92  		t.Skipf("no pthreads on %s", runtime.GOOS)
		93  	}
		94  	if runtime.GOARCH == "ppc64" && runtime.GOOS == "linux" {
		95  		// TODO(austin) External linking not implemented on
		96  		// linux/ppc64 (issue #8912)
		97  		t.Skipf("no external linking on ppc64")
		98  	}
		99  
	 100  	exe, err := buildTestProg(t, "testprogcgo", "-tags=threadprof")
	 101  	if err != nil {
	 102  		t.Fatal(err)
	 103  	}
	 104  
	 105  	got, err := testenv.CleanCmdEnv(exec.Command(exe, "CgoExternalThreadSIGPROF")).CombinedOutput()
	 106  	if err != nil {
	 107  		t.Fatalf("exit status: %v\n%s", err, got)
	 108  	}
	 109  
	 110  	if want := "OK\n"; string(got) != want {
	 111  		t.Fatalf("expected %q, but got:\n%s", want, got)
	 112  	}
	 113  }
	 114  
	 115  func TestCgoExternalThreadSignal(t *testing.T) {
	 116  	t.Parallel()
	 117  	// issue 10139
	 118  	switch runtime.GOOS {
	 119  	case "plan9", "windows":
	 120  		t.Skipf("no pthreads on %s", runtime.GOOS)
	 121  	}
	 122  
	 123  	exe, err := buildTestProg(t, "testprogcgo", "-tags=threadprof")
	 124  	if err != nil {
	 125  		t.Fatal(err)
	 126  	}
	 127  
	 128  	got, err := testenv.CleanCmdEnv(exec.Command(exe, "CgoExternalThreadSIGPROF")).CombinedOutput()
	 129  	if err != nil {
	 130  		t.Fatalf("exit status: %v\n%s", err, got)
	 131  	}
	 132  
	 133  	want := []byte("OK\n")
	 134  	if !bytes.Equal(got, want) {
	 135  		t.Fatalf("expected %q, but got:\n%s", want, got)
	 136  	}
	 137  }
	 138  
	 139  func TestCgoDLLImports(t *testing.T) {
	 140  	// test issue 9356
	 141  	if runtime.GOOS != "windows" {
	 142  		t.Skip("skipping windows specific test")
	 143  	}
	 144  	got := runTestProg(t, "testprogcgo", "CgoDLLImportsMain")
	 145  	want := "OK\n"
	 146  	if got != want {
	 147  		t.Fatalf("expected %q, but got %v", want, got)
	 148  	}
	 149  }
	 150  
	 151  func TestCgoExecSignalMask(t *testing.T) {
	 152  	t.Parallel()
	 153  	// Test issue 13164.
	 154  	switch runtime.GOOS {
	 155  	case "windows", "plan9":
	 156  		t.Skipf("skipping signal mask test on %s", runtime.GOOS)
	 157  	}
	 158  	got := runTestProg(t, "testprogcgo", "CgoExecSignalMask", "GOTRACEBACK=system")
	 159  	want := "OK\n"
	 160  	if got != want {
	 161  		t.Errorf("expected %q, got %v", want, got)
	 162  	}
	 163  }
	 164  
	 165  func TestEnsureDropM(t *testing.T) {
	 166  	t.Parallel()
	 167  	// Test for issue 13881.
	 168  	switch runtime.GOOS {
	 169  	case "windows", "plan9":
	 170  		t.Skipf("skipping dropm test on %s", runtime.GOOS)
	 171  	}
	 172  	got := runTestProg(t, "testprogcgo", "EnsureDropM")
	 173  	want := "OK\n"
	 174  	if got != want {
	 175  		t.Errorf("expected %q, got %v", want, got)
	 176  	}
	 177  }
	 178  
	 179  // Test for issue 14387.
	 180  // Test that the program that doesn't need any cgo pointer checking
	 181  // takes about the same amount of time with it as without it.
	 182  func TestCgoCheckBytes(t *testing.T) {
	 183  	t.Parallel()
	 184  	// Make sure we don't count the build time as part of the run time.
	 185  	testenv.MustHaveGoBuild(t)
	 186  	exe, err := buildTestProg(t, "testprogcgo")
	 187  	if err != nil {
	 188  		t.Fatal(err)
	 189  	}
	 190  
	 191  	// Try it 10 times to avoid flakiness.
	 192  	const tries = 10
	 193  	var tot1, tot2 time.Duration
	 194  	for i := 0; i < tries; i++ {
	 195  		cmd := testenv.CleanCmdEnv(exec.Command(exe, "CgoCheckBytes"))
	 196  		cmd.Env = append(cmd.Env, "GODEBUG=cgocheck=0", fmt.Sprintf("GO_CGOCHECKBYTES_TRY=%d", i))
	 197  
	 198  		start := time.Now()
	 199  		cmd.Run()
	 200  		d1 := time.Since(start)
	 201  
	 202  		cmd = testenv.CleanCmdEnv(exec.Command(exe, "CgoCheckBytes"))
	 203  		cmd.Env = append(cmd.Env, fmt.Sprintf("GO_CGOCHECKBYTES_TRY=%d", i))
	 204  
	 205  		start = time.Now()
	 206  		cmd.Run()
	 207  		d2 := time.Since(start)
	 208  
	 209  		if d1*20 > d2 {
	 210  			// The slow version (d2) was less than 20 times
	 211  			// slower than the fast version (d1), so OK.
	 212  			return
	 213  		}
	 214  
	 215  		tot1 += d1
	 216  		tot2 += d2
	 217  	}
	 218  
	 219  	t.Errorf("cgo check too slow: got %v, expected at most %v", tot2/tries, (tot1/tries)*20)
	 220  }
	 221  
	 222  func TestCgoPanicDeadlock(t *testing.T) {
	 223  	t.Parallel()
	 224  	// test issue 14432
	 225  	got := runTestProg(t, "testprogcgo", "CgoPanicDeadlock")
	 226  	want := "panic: cgo error\n\n"
	 227  	if !strings.HasPrefix(got, want) {
	 228  		t.Fatalf("output does not start with %q:\n%s", want, got)
	 229  	}
	 230  }
	 231  
	 232  func TestCgoCCodeSIGPROF(t *testing.T) {
	 233  	t.Parallel()
	 234  	got := runTestProg(t, "testprogcgo", "CgoCCodeSIGPROF")
	 235  	want := "OK\n"
	 236  	if got != want {
	 237  		t.Errorf("expected %q got %v", want, got)
	 238  	}
	 239  }
	 240  
	 241  func TestCgoCrashTraceback(t *testing.T) {
	 242  	t.Parallel()
	 243  	switch platform := runtime.GOOS + "/" + runtime.GOARCH; platform {
	 244  	case "darwin/amd64":
	 245  	case "linux/amd64":
	 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/ppc64le":
	 264  	default:
	 265  		t.Skipf("not yet supported on %s", platform)
	 266  	}
	 267  	got := runTestProg(t, "testprogcgo", "CrashTracebackGo")
	 268  	for i := 1; i <= 3; i++ {
	 269  		want := fmt.Sprintf("main.h%d", i)
	 270  		if !strings.Contains(got, want) {
	 271  			t.Errorf("missing %s", want)
	 272  		}
	 273  	}
	 274  }
	 275  
	 276  func TestCgoTracebackContext(t *testing.T) {
	 277  	t.Parallel()
	 278  	got := runTestProg(t, "testprogcgo", "TracebackContext")
	 279  	want := "OK\n"
	 280  	if got != want {
	 281  		t.Errorf("expected %q got %v", want, got)
	 282  	}
	 283  }
	 284  
	 285  func TestCgoTracebackContextPreemption(t *testing.T) {
	 286  	t.Parallel()
	 287  	got := runTestProg(t, "testprogcgo", "TracebackContextPreemption")
	 288  	want := "OK\n"
	 289  	if got != want {
	 290  		t.Errorf("expected %q got %v", want, got)
	 291  	}
	 292  }
	 293  
	 294  func testCgoPprof(t *testing.T, buildArg, runArg, top, bottom string) {
	 295  	t.Parallel()
	 296  	if runtime.GOOS != "linux" || (runtime.GOARCH != "amd64" && runtime.GOARCH != "ppc64le") {
	 297  		t.Skipf("not yet supported on %s/%s", runtime.GOOS, runtime.GOARCH)
	 298  	}
	 299  	testenv.MustHaveGoRun(t)
	 300  
	 301  	exe, err := buildTestProg(t, "testprogcgo", buildArg)
	 302  	if err != nil {
	 303  		t.Fatal(err)
	 304  	}
	 305  
	 306  	// pprofCgoTraceback is called whenever CGO code is executing and a signal
	 307  	// is received. Disable signal preemption to increase the likelihood at
	 308  	// least one SIGPROF signal fired to capture a sample. See issue #37201.
	 309  	cmd := testenv.CleanCmdEnv(exec.Command(exe, runArg))
	 310  	cmd.Env = append(cmd.Env, "GODEBUG=asyncpreemptoff=1")
	 311  
	 312  	got, err := cmd.CombinedOutput()
	 313  	if err != nil {
	 314  		if testenv.Builder() == "linux-amd64-alpine" {
	 315  			// See Issue 18243 and Issue 19938.
	 316  			t.Skipf("Skipping failing test on Alpine (golang.org/issue/18243). Ignoring error: %v", err)
	 317  		}
	 318  		t.Fatalf("%s\n\n%v", got, err)
	 319  	}
	 320  	fn := strings.TrimSpace(string(got))
	 321  	defer os.Remove(fn)
	 322  
	 323  	for try := 0; try < 2; try++ {
	 324  		cmd := testenv.CleanCmdEnv(exec.Command(testenv.GoToolPath(t), "tool", "pprof", "-traces"))
	 325  		// Check that pprof works both with and without explicit executable on command line.
	 326  		if try == 0 {
	 327  			cmd.Args = append(cmd.Args, exe, fn)
	 328  		} else {
	 329  			cmd.Args = append(cmd.Args, fn)
	 330  		}
	 331  
	 332  		found := false
	 333  		for i, e := range cmd.Env {
	 334  			if strings.HasPrefix(e, "PPROF_TMPDIR=") {
	 335  				cmd.Env[i] = "PPROF_TMPDIR=" + os.TempDir()
	 336  				found = true
	 337  				break
	 338  			}
	 339  		}
	 340  		if !found {
	 341  			cmd.Env = append(cmd.Env, "PPROF_TMPDIR="+os.TempDir())
	 342  		}
	 343  
	 344  		out, err := cmd.CombinedOutput()
	 345  		t.Logf("%s:\n%s", cmd.Args, out)
	 346  		if err != nil {
	 347  			t.Error(err)
	 348  			continue
	 349  		}
	 350  
	 351  		trace := findTrace(string(out), top)
	 352  		if len(trace) == 0 {
	 353  			t.Errorf("%s traceback missing.", top)
	 354  			continue
	 355  		}
	 356  		if trace[len(trace)-1] != bottom {
	 357  			t.Errorf("invalid traceback origin: got=%v; want=[%s ... %s]", trace, top, bottom)
	 358  		}
	 359  	}
	 360  }
	 361  
	 362  func TestCgoPprof(t *testing.T) {
	 363  	testCgoPprof(t, "", "CgoPprof", "cpuHog", "runtime.main")
	 364  }
	 365  
	 366  func TestCgoPprofPIE(t *testing.T) {
	 367  	testCgoPprof(t, "-buildmode=pie", "CgoPprof", "cpuHog", "runtime.main")
	 368  }
	 369  
	 370  func TestCgoPprofThread(t *testing.T) {
	 371  	testCgoPprof(t, "", "CgoPprofThread", "cpuHogThread", "cpuHogThread2")
	 372  }
	 373  
	 374  func TestCgoPprofThreadNoTraceback(t *testing.T) {
	 375  	testCgoPprof(t, "", "CgoPprofThreadNoTraceback", "cpuHogThread", "runtime._ExternalCode")
	 376  }
	 377  
	 378  func TestRaceProf(t *testing.T) {
	 379  	if (runtime.GOOS != "linux" && runtime.GOOS != "freebsd") || runtime.GOARCH != "amd64" {
	 380  		t.Skipf("not yet supported on %s/%s", runtime.GOOS, runtime.GOARCH)
	 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  	t.Parallel()
	 408  	if (runtime.GOOS != "linux" && runtime.GOOS != "freebsd") || runtime.GOARCH != "amd64" {
	 409  		t.Skipf("not yet supported on %s/%s", runtime.GOOS, runtime.GOARCH)
	 410  	}
	 411  
	 412  	testenv.MustHaveGoRun(t)
	 413  
	 414  	// This test requires building various packages with -race, so
	 415  	// it's somewhat slow.
	 416  	if testing.Short() {
	 417  		t.Skip("skipping test in -short mode")
	 418  	}
	 419  
	 420  	exe, err := buildTestProg(t, "testprogcgo", "-race")
	 421  	if err != nil {
	 422  		t.Fatal(err)
	 423  	}
	 424  
	 425  	got, err := testenv.CleanCmdEnv(exec.Command(exe, "CgoRaceSignal")).CombinedOutput()
	 426  	if err != nil {
	 427  		t.Logf("%s\n", got)
	 428  		t.Fatal(err)
	 429  	}
	 430  	want := "OK\n"
	 431  	if string(got) != want {
	 432  		t.Errorf("expected %q got %s", want, got)
	 433  	}
	 434  }
	 435  
	 436  func TestCgoNumGoroutine(t *testing.T) {
	 437  	switch runtime.GOOS {
	 438  	case "windows", "plan9":
	 439  		t.Skipf("skipping numgoroutine test on %s", runtime.GOOS)
	 440  	}
	 441  	t.Parallel()
	 442  	got := runTestProg(t, "testprogcgo", "NumGoroutine")
	 443  	want := "OK\n"
	 444  	if got != want {
	 445  		t.Errorf("expected %q got %v", want, got)
	 446  	}
	 447  }
	 448  
	 449  func TestCatchPanic(t *testing.T) {
	 450  	t.Parallel()
	 451  	switch runtime.GOOS {
	 452  	case "plan9", "windows":
	 453  		t.Skipf("no signals on %s", runtime.GOOS)
	 454  	case "darwin":
	 455  		if runtime.GOARCH == "amd64" {
	 456  			t.Skipf("crash() on darwin/amd64 doesn't raise SIGABRT")
	 457  		}
	 458  	}
	 459  
	 460  	testenv.MustHaveGoRun(t)
	 461  
	 462  	exe, err := buildTestProg(t, "testprogcgo")
	 463  	if err != nil {
	 464  		t.Fatal(err)
	 465  	}
	 466  
	 467  	for _, early := range []bool{true, false} {
	 468  		cmd := testenv.CleanCmdEnv(exec.Command(exe, "CgoCatchPanic"))
	 469  		// Make sure a panic results in a crash.
	 470  		cmd.Env = append(cmd.Env, "GOTRACEBACK=crash")
	 471  		if early {
	 472  			// Tell testprogcgo to install an early signal handler for SIGABRT
	 473  			cmd.Env = append(cmd.Env, "CGOCATCHPANIC_EARLY_HANDLER=1")
	 474  		}
	 475  		if out, err := cmd.CombinedOutput(); err != nil {
	 476  			t.Errorf("testprogcgo CgoCatchPanic failed: %v\n%s", err, out)
	 477  		}
	 478  	}
	 479  }
	 480  
	 481  func TestCgoLockOSThreadExit(t *testing.T) {
	 482  	switch runtime.GOOS {
	 483  	case "plan9", "windows":
	 484  		t.Skipf("no pthreads on %s", runtime.GOOS)
	 485  	}
	 486  	t.Parallel()
	 487  	testLockOSThreadExit(t, "testprogcgo")
	 488  }
	 489  
	 490  func TestWindowsStackMemoryCgo(t *testing.T) {
	 491  	if runtime.GOOS != "windows" {
	 492  		t.Skip("skipping windows specific test")
	 493  	}
	 494  	testenv.SkipFlaky(t, 22575)
	 495  	o := runTestProg(t, "testprogcgo", "StackMemory")
	 496  	stackUsage, err := strconv.Atoi(o)
	 497  	if err != nil {
	 498  		t.Fatalf("Failed to read stack usage: %v", err)
	 499  	}
	 500  	if expected, got := 100<<10, stackUsage; got > expected {
	 501  		t.Fatalf("expected < %d bytes of memory per thread, got %d", expected, got)
	 502  	}
	 503  }
	 504  
	 505  func TestSigStackSwapping(t *testing.T) {
	 506  	switch runtime.GOOS {
	 507  	case "plan9", "windows":
	 508  		t.Skipf("no sigaltstack on %s", runtime.GOOS)
	 509  	}
	 510  	t.Parallel()
	 511  	got := runTestProg(t, "testprogcgo", "SigStack")
	 512  	want := "OK\n"
	 513  	if got != want {
	 514  		t.Errorf("expected %q got %v", want, got)
	 515  	}
	 516  }
	 517  
	 518  func TestCgoTracebackSigpanic(t *testing.T) {
	 519  	// Test unwinding over a sigpanic in C code without a C
	 520  	// symbolizer. See issue #23576.
	 521  	if runtime.GOOS == "windows" {
	 522  		// On Windows if we get an exception in C code, we let
	 523  		// the Windows exception handler unwind it, rather
	 524  		// than injecting a sigpanic.
	 525  		t.Skip("no sigpanic in C on windows")
	 526  	}
	 527  	t.Parallel()
	 528  	got := runTestProg(t, "testprogcgo", "TracebackSigpanic")
	 529  	want := "runtime.sigpanic"
	 530  	if !strings.Contains(got, want) {
	 531  		t.Fatalf("want failure containing %q. output:\n%s\n", want, got)
	 532  	}
	 533  	nowant := "unexpected return pc"
	 534  	if strings.Contains(got, nowant) {
	 535  		t.Fatalf("failure incorrectly contains %q. output:\n%s\n", nowant, got)
	 536  	}
	 537  }
	 538  
	 539  // Test that C code called via cgo can use large Windows thread stacks
	 540  // and call back in to Go without crashing. See issue #20975.
	 541  //
	 542  // See also TestBigStackCallbackSyscall.
	 543  func TestBigStackCallbackCgo(t *testing.T) {
	 544  	if runtime.GOOS != "windows" {
	 545  		t.Skip("skipping windows specific test")
	 546  	}
	 547  	t.Parallel()
	 548  	got := runTestProg(t, "testprogcgo", "BigStack")
	 549  	want := "OK\n"
	 550  	if got != want {
	 551  		t.Errorf("expected %q got %v", want, got)
	 552  	}
	 553  }
	 554  
	 555  func nextTrace(lines []string) ([]string, []string) {
	 556  	var trace []string
	 557  	for n, line := range lines {
	 558  		if strings.HasPrefix(line, "---") {
	 559  			return trace, lines[n+1:]
	 560  		}
	 561  		fields := strings.Fields(strings.TrimSpace(line))
	 562  		if len(fields) == 0 {
	 563  			continue
	 564  		}
	 565  		// Last field contains the function name.
	 566  		trace = append(trace, fields[len(fields)-1])
	 567  	}
	 568  	return nil, nil
	 569  }
	 570  
	 571  func findTrace(text, top string) []string {
	 572  	lines := strings.Split(text, "\n")
	 573  	_, lines = nextTrace(lines) // Skip the header.
	 574  	for len(lines) > 0 {
	 575  		var t []string
	 576  		t, lines = nextTrace(lines)
	 577  		if len(t) == 0 {
	 578  			continue
	 579  		}
	 580  		if t[0] == top {
	 581  			return t
	 582  		}
	 583  	}
	 584  	return nil
	 585  }
	 586  
	 587  func TestSegv(t *testing.T) {
	 588  	switch runtime.GOOS {
	 589  	case "plan9", "windows":
	 590  		t.Skipf("no signals on %s", runtime.GOOS)
	 591  	}
	 592  
	 593  	for _, test := range []string{"Segv", "SegvInCgo"} {
	 594  		t.Run(test, func(t *testing.T) {
	 595  			t.Parallel()
	 596  			got := runTestProg(t, "testprogcgo", test)
	 597  			t.Log(got)
	 598  			if !strings.Contains(got, "SIGSEGV") {
	 599  				t.Errorf("expected crash from signal")
	 600  			}
	 601  		})
	 602  	}
	 603  }
	 604  
	 605  // TestEINTR tests that we handle EINTR correctly.
	 606  // See issue #20400 and friends.
	 607  func TestEINTR(t *testing.T) {
	 608  	switch runtime.GOOS {
	 609  	case "plan9", "windows":
	 610  		t.Skipf("no EINTR on %s", runtime.GOOS)
	 611  	case "linux":
	 612  		if runtime.GOARCH == "386" {
	 613  			// On linux-386 the Go signal handler sets
	 614  			// a restorer function that is not preserved
	 615  			// by the C sigaction call in the test,
	 616  			// causing the signal handler to crash when
	 617  			// returning the normal code. The test is not
	 618  			// architecture-specific, so just skip on 386
	 619  			// rather than doing a complicated workaround.
	 620  			t.Skip("skipping on linux-386; C sigaction does not preserve Go restorer")
	 621  		}
	 622  	}
	 623  
	 624  	t.Parallel()
	 625  	output := runTestProg(t, "testprogcgo", "EINTR")
	 626  	want := "OK\n"
	 627  	if output != want {
	 628  		t.Fatalf("want %s, got %s\n", want, output)
	 629  	}
	 630  }
	 631  
	 632  // Issue #42207.
	 633  func TestNeedmDeadlock(t *testing.T) {
	 634  	switch runtime.GOOS {
	 635  	case "plan9", "windows":
	 636  		t.Skipf("no signals on %s", runtime.GOOS)
	 637  	}
	 638  	output := runTestProg(t, "testprogcgo", "NeedmDeadlock")
	 639  	want := "OK\n"
	 640  	if output != want {
	 641  		t.Fatalf("want %s, got %s\n", want, output)
	 642  	}
	 643  }
	 644  

View as plain text