1
2
3
4
5 package main
6
7 import (
8 "internal/asan"
9 "internal/race"
10 "runtime"
11 "runtime/debug"
12 "unsafe"
13 )
14
15 func init() {
16 register("DetectFinalizerAndCleanupLeaks", DetectFinalizerAndCleanupLeaks)
17 }
18
19 type tiny uint8
20
21 var tinySink *tiny
22
23
24 func DetectFinalizerAndCleanupLeaks() {
25 type T *int
26
27 defer debug.SetGCPercent(debug.SetGCPercent(-1))
28
29
30 cLeak := new(T)
31 runtime.AddCleanup(cLeak, func(x int) {
32 **cLeak = x
33 }, int(0))
34
35
36 cNoLeak := new(T)
37 runtime.AddCleanup(cNoLeak, func(_ int) {}, int(0))
38
39
40 runtime.AddCleanup(cNoLeak, func(x int) {
41 **cNoLeak = x
42 }, int(0)).Stop()
43
44 if !asan.Enabled && !race.Enabled {
45
46
47
48
49 var ctLeak *tiny
50 for {
51 tinySink = ctLeak
52 ctLeak = new(tiny)
53 *ctLeak = tiny(55)
54
55
56
57 if uintptr(unsafe.Pointer(ctLeak))%2 != 0 {
58 break
59 }
60 }
61 runtime.AddCleanup(ctLeak, func(_ struct{}) {}, struct{}{})
62 }
63
64
65 fLeak := new(T)
66 runtime.SetFinalizer(fLeak, func(_ *T) {
67 **fLeak = 12
68 })
69
70
71 fNoLeak := new(T)
72 runtime.SetFinalizer(fNoLeak, func(x *T) {
73 **x = 51
74 })
75
76
77 runtime.GC()
78 println("OK")
79 }
80
View as plain text