Skip to content

Commit 77668dd

Browse files
committed
Adding internal leak detection lib
Signed-off-by: apostasie <[email protected]>
1 parent 5af8ab3 commit 77668dd

File tree

5 files changed

+181
-0
lines changed

5 files changed

+181
-0
lines changed

mod/tigron/go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ go 1.23
44

55
require (
66
github.com/creack/pty v1.1.24
7+
go.uber.org/goleak v1.3.0
78
golang.org/x/sync v0.11.0
89
golang.org/x/term v0.29.0
910
gotest.tools/v3 v3.5.2

mod/tigron/go.sum

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,22 @@
11
github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s=
22
github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE=
3+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
4+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
35
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
46
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
7+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
8+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
9+
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
10+
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
11+
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
12+
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
513
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
614
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
715
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
816
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
917
golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
1018
golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
19+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
20+
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
1121
gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
1222
gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=

mod/tigron/internal/highk/doc.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
Copyright The containerd Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
// Package highk (for "high-κ dielectric") is a highly experimental leak detection library
18+
// (for file descriptors and go routines).
19+
// It is purely internal for now and used only as part of the tests for tigron.
20+
// TODO:
21+
// - get rid of lsof and implement in go
22+
// - investigate feasibility of adding automatic leak detection for any test using tigron
23+
// - investigate feasibility of adding leak detection for tested binaries
24+
// - review usefulness of uber goroutines leak library
25+
package highk
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/*
2+
Copyright The containerd Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package highk
18+
19+
import (
20+
"io"
21+
"os"
22+
"os/exec"
23+
"slices"
24+
"strconv"
25+
"strings"
26+
"syscall"
27+
)
28+
29+
// FIXME: it seems that lsof (or go test) is interefering and showing false positive KQUEUE / inodes
30+
//
31+
//nolint:gochecknoglobals
32+
var whitelist = map[string]bool{
33+
"5u KQUEUE": true,
34+
"10u a_inode": true,
35+
}
36+
37+
// SnapshotOpenFiles will capture the list of currently open-files for the process.
38+
//
39+
//nolint:wrapcheck
40+
func SnapshotOpenFiles(file *os.File) ([]byte, error) {
41+
// Using a buffer would add a pipe to the list of files
42+
// Reimplement this stuff in go ASAP and toss lsof instead of passing around fd
43+
// defer fd.Close()
44+
_, _ = file.Seek(0, 0)
45+
_ = file.Truncate(0)
46+
47+
exe, err := exec.LookPath("lsof")
48+
if err != nil {
49+
return nil, err
50+
}
51+
52+
//nolint:gosec
53+
cmd := exec.Command(exe, "-nP", "-p", strconv.Itoa(syscall.Getpid()))
54+
cmd.Stdout = file
55+
56+
_ = cmd.Run()
57+
58+
_, _ = file.Seek(0, 0)
59+
60+
return io.ReadAll(file)
61+
}
62+
63+
// Diff will return a slice of strings showing the diff between two strings.
64+
func Diff(one, two string) []string {
65+
aone := strings.Split(one, "\n")
66+
atwo := strings.Split(two, "\n")
67+
68+
slices.Sort(aone)
69+
slices.Sort(atwo)
70+
71+
loss := make(map[string]bool, len(aone))
72+
gain := map[string]bool{}
73+
74+
for _, v := range aone {
75+
loss[v] = true
76+
}
77+
78+
for _, v := range atwo {
79+
if _, ok := loss[v]; ok {
80+
delete(loss, v)
81+
} else {
82+
gain[v] = true
83+
}
84+
}
85+
86+
diff := []string{}
87+
88+
for key := range loss {
89+
legit := true
90+
91+
for wl := range whitelist {
92+
if strings.Contains(key, wl) {
93+
legit = false
94+
}
95+
}
96+
97+
if legit {
98+
diff = append(diff, "- "+key)
99+
}
100+
}
101+
102+
for key := range gain {
103+
legit := true
104+
105+
for wl := range whitelist {
106+
if strings.Contains(key, wl) {
107+
legit = false
108+
}
109+
}
110+
111+
if legit {
112+
diff = append(diff, "+ "+key)
113+
}
114+
}
115+
116+
return diff
117+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
Copyright The containerd Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package highk
18+
19+
import (
20+
"go.uber.org/goleak"
21+
)
22+
23+
// FindGoRoutines retrieves leaked go routines.
24+
//
25+
//nolint:wrapcheck
26+
func FindGoRoutines() error {
27+
return goleak.Find()
28+
}

0 commit comments

Comments
 (0)