1// run
2
3// Copyright 2019 The Go Authors. All rights reserved.
4// Use of this source code is governed by a BSD-style
5// license that can be found in the LICENSE file.
6
7// Make sure we use the deferreturn live map instead of
8// the entry live map when handling a segv in a function
9// that defers.
10
11package main
12
13import "runtime"
14
15var finalized bool
16var err string
17
18type HeapObj [8]int64
19
20const filler int64 = 0x123456789abcdef0
21
22func (h *HeapObj) init() {
23	for i := 0; i < len(*h); i++ {
24		h[i] = filler
25	}
26}
27func (h *HeapObj) check() {
28	for i := 0; i < len(*h); i++ {
29		if h[i] != filler {
30			err = "filler overwritten"
31		}
32	}
33}
34
35func gc(shouldFinalize bool) {
36	runtime.GC()
37	runtime.GC()
38	runtime.GC()
39	if shouldFinalize != finalized {
40		err = "heap object finalized at the wrong time"
41	}
42}
43
44func main() {
45	h := new(HeapObj)
46	h.init()
47	runtime.SetFinalizer(h, func(h *HeapObj) {
48		finalized = true
49	})
50
51	gc(false)
52	g(h)
53	if err != "" {
54		panic(err)
55	}
56}
57
58func g(h *HeapObj) {
59	gc(false)
60	h.check()
61	// h is now unused
62	defer func() {
63		// h should not be live here. Previously we used to
64		// use the function entry point as the place to get
65		// the live map when handling a segv.
66		gc(true)
67		recover()
68	}()
69	*(*int)(nil) = 0 // trigger a segv
70	return
71}
72