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