• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2014 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// Test that SIGSETXID runs on signal stack, since it's likely to
6// overflow if it runs on the Go stack.
7
8package cgotest
9
10/*
11#include <sys/types.h>
12#include <unistd.h>
13*/
14import "C"
15
16import (
17	"runtime"
18	"runtime/debug"
19	"sync/atomic"
20	"testing"
21
22	"cmd/cgo/internal/test/issue9400"
23)
24
25func test9400(t *testing.T) {
26	// We synchronize through a shared variable, so we need two procs
27	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(2))
28
29	// Start signaller
30	atomic.StoreInt32(&issue9400.Baton, 0)
31	go func() {
32		// Wait for RewindAndSetgid
33		for atomic.LoadInt32(&issue9400.Baton) == 0 {
34			runtime.Gosched()
35		}
36		// Broadcast SIGSETXID
37		runtime.LockOSThread()
38		C.setgid(0)
39		// Indicate that signalling is done
40		atomic.StoreInt32(&issue9400.Baton, 0)
41	}()
42
43	// Grow the stack and put down a test pattern
44	const pattern = 0x123456789abcdef
45	var big [1024]uint64 // len must match assembly
46	for i := range big {
47		big[i] = pattern
48	}
49
50	// Disable GC for the duration of the test.
51	// This avoids a potential GC deadlock when spinning in uninterruptible ASM below #49695.
52	defer debug.SetGCPercent(debug.SetGCPercent(-1))
53	// SetGCPercent waits until the mark phase is over, but the runtime
54	// also preempts at the start of the sweep phase, so make sure that's
55	// done too. See #49695.
56	runtime.GC()
57
58	// Temporarily rewind the stack and trigger SIGSETXID
59	issue9400.RewindAndSetgid()
60
61	// Check test pattern
62	for i := range big {
63		if big[i] != pattern {
64			t.Fatalf("entry %d of test pattern is wrong; %#x != %#x", i, big[i], uint64(pattern))
65		}
66	}
67}
68