Skip to content

Commit c57654b

Browse files
authored
Merge pull request #4044 from apostasie/ci-tigron-break-3
[CI] Tigron breakout 3: leak detection
2 parents 5bfe6eb + c9c90d9 commit c57654b

File tree

8 files changed

+185
-5
lines changed

8 files changed

+185
-5
lines changed

Diff for: go.sum

+2-2
Original file line numberDiff line numberDiff line change
@@ -325,8 +325,8 @@ go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4Jjx
325325
go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8=
326326
go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys=
327327
go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A=
328-
go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA=
329-
go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
328+
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
329+
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
330330
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
331331
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
332332
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=

Diff for: mod/tigron/.golangci.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ linters:
2525
files:
2626
- $all
2727
allow:
28-
2928
- $gostd
3029
- github.com/containerd/nerdctl/mod/tigron
3130
- github.com/creack/pty
3231
- golang.org/x/sync
3332
- golang.org/x/term
3433
- gotest.tools/v3
34+
- go.uber.org/goleak
3535
staticcheck:
3636
checks:
3737
- all

Diff for: mod/tigron/Makefile

+2-2
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ install-dev-tools:
181181
##########################
182182
test-unit:
183183
$(call title, $@)
184-
@go test $(VERBOSE_FLAG) $(MAKEFILE_DIR)/...
184+
@HIGHK_EXPERIMENTAL_FD=true go test $(VERBOSE_FLAG) $(MAKEFILE_DIR)/...
185185
$(call footer, $@)
186186

187187
test-unit-bench:
@@ -191,7 +191,7 @@ test-unit-bench:
191191

192192
test-unit-race:
193193
$(call title, $@)
194-
@CGO_ENABLED=1 go test $(VERBOSE_FLAG) $(MAKEFILE_DIR)/... -race
194+
@HIGHK_EXPERIMENTAL_FD=true CGO_ENABLED=1 go test $(VERBOSE_FLAG) $(MAKEFILE_DIR)/... -race
195195
$(call footer, $@)
196196

197197
.PHONY: \

Diff for: mod/tigron/go.mod

+1
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

Diff for: mod/tigron/go.sum

+10
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=

Diff for: mod/tigron/internal/highk/doc.go

+25
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

Diff for: mod/tigron/internal/highk/fileleak.go

+116
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
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+
_, _ = file.Seek(0, 0)
44+
_ = file.Truncate(0)
45+
46+
exe, err := exec.LookPath("lsof")
47+
if err != nil {
48+
return nil, err
49+
}
50+
51+
//nolint:gosec
52+
cmd := exec.Command(exe, "-nP", "-p", strconv.Itoa(syscall.Getpid()))
53+
cmd.Stdout = file
54+
55+
_ = cmd.Run()
56+
57+
_, _ = file.Seek(0, 0)
58+
59+
return io.ReadAll(file)
60+
}
61+
62+
// Diff will return a slice of strings showing the diff between two strings.
63+
func Diff(one, two string) []string {
64+
aone := strings.Split(one, "\n")
65+
atwo := strings.Split(two, "\n")
66+
67+
slices.Sort(aone)
68+
slices.Sort(atwo)
69+
70+
loss := make(map[string]bool, len(aone))
71+
gain := map[string]bool{}
72+
73+
for _, v := range aone {
74+
loss[v] = true
75+
}
76+
77+
for _, v := range atwo {
78+
if _, ok := loss[v]; ok {
79+
delete(loss, v)
80+
} else {
81+
gain[v] = true
82+
}
83+
}
84+
85+
diff := []string{}
86+
87+
for key := range loss {
88+
legit := true
89+
90+
for wl := range whitelist {
91+
if strings.Contains(key, wl) {
92+
legit = false
93+
}
94+
}
95+
96+
if legit {
97+
diff = append(diff, "- "+key)
98+
}
99+
}
100+
101+
for key := range gain {
102+
legit := true
103+
104+
for wl := range whitelist {
105+
if strings.Contains(key, wl) {
106+
legit = false
107+
}
108+
}
109+
110+
if legit {
111+
diff = append(diff, "+ "+key)
112+
}
113+
}
114+
115+
return diff
116+
}

Diff for: mod/tigron/internal/highk/goroutines.go

+28
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, which are returned as an error.
24+
//
25+
//nolint:wrapcheck
26+
func FindGoRoutines() error {
27+
return goleak.Find()
28+
}

0 commit comments

Comments
 (0)