Enable reference count leak checking for lisafs.

Also add DoRepeatedLeakCheck() to refsvfs2 package.

Updates #5466

PiperOrigin-RevId: 425004987
This commit is contained in:
Ayush Ranjan
2022-01-28 19:14:08 -08:00
committed by gVisor bot
parent 44f0f2dc40
commit 2a3d59997f
6 changed files with 50 additions and 22 deletions
+1
View File
@@ -104,6 +104,7 @@ func runServerClient(t testing.TB, clientFn func(c *lisafs.Client)) {
c.Close() // This should trigger client and server shutdown.
ts.Wait()
ts.Server.Destroy()
}
// TestStartUp tests that the server and client can be started up correctly.
+5
View File
@@ -103,6 +103,11 @@ func (s *Server) Wait() {
s.connWg.Wait()
}
// Destroy releases resources being used by this server.
func (s *Server) Destroy() {
s.root.DecRef(nil)
}
// ServerImpl contains the implementation details for a Server.
// Implementations of ServerImpl should contain their associated Server by
// value as their first field.
+2
View File
@@ -13,6 +13,8 @@ go_library(
"//pkg/abi/linux",
"//pkg/context",
"//pkg/lisafs",
"//pkg/refs",
"//pkg/refsvfs2",
"//pkg/unet",
"@com_github_syndtr_gocapability//capability:go_default_library",
"@org_golang_x_sys//unix:go_default_library",
+13 -5
View File
@@ -30,6 +30,8 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
"gvisor.dev/gvisor/pkg/lisafs"
"gvisor.dev/gvisor/pkg/refs"
"gvisor.dev/gvisor/pkg/refsvfs2"
"gvisor.dev/gvisor/pkg/unet"
)
@@ -49,10 +51,9 @@ type Tester interface {
// RunAllLocalFSTests runs all local FS tests as subtests.
func RunAllLocalFSTests(t *testing.T, tester Tester) {
refs.SetLeakMode(refs.LeaksPanic)
for name, testFn := range localFSTests {
t.Run(name, func(t *testing.T) {
runServerClient(t, tester, testFn)
})
runServerClient(t, tester, name, testFn)
}
}
@@ -74,7 +75,7 @@ var localFSTests map[string]testFunc = map[string]testFunc{
"Getdents": testGetdents,
}
func runServerClient(t *testing.T, tester Tester, testFn testFunc) {
func runServerClient(t *testing.T, tester Tester, testName string, testFn testFunc) {
mountPath, err := ioutil.TempDir(os.Getenv("TEST_TMPDIR"), "")
if err != nil {
t.Fatalf("creation of temporary mountpoint failed: %v", err)
@@ -109,9 +110,16 @@ func runServerClient(t *testing.T, tester Tester, testFn testFunc) {
rootFile := c.NewFD(root.ControlFD)
ctx := context.Background()
testFn(ctx, t, tester, rootFile)
t.Run(testName, func(t *testing.T) {
testFn(ctx, t, tester, rootFile)
})
closeFD(ctx, t, rootFile)
// Release server resources and check for leaks. Note that leak check must
// happen before c.Close() because server cleans up resources on shutdown.
server.Destroy()
refsvfs2.DoRepeatedLeakCheck()
c.Close() // This should trigger client and server shutdown.
server.Wait()
}
+28 -17
View File
@@ -124,24 +124,35 @@ func logEvent(obj CheckedObject, msg string) {
var checkOnce sync.Once
// DoLeakCheck iterates through the live object map and logs a message for each
// object. It is called once no reference-counted objects should be reachable
// anymore, at which point anything left in the map is considered a leak.
// object. It should be called when no reference-counted objects are reachable
// anymore, at which point anything left in the map is considered a leak. On
// multiple calls, only the first call will perform the leak check.
func DoLeakCheck() {
if leakCheckEnabled() {
checkOnce.Do(func() {
liveObjectsMu.Lock()
defer liveObjectsMu.Unlock()
leaked := len(liveObjects)
if leaked > 0 {
msg := fmt.Sprintf("Leak checking detected %d leaked objects:\n", leaked)
for obj := range liveObjects {
msg += obj.LeakMessage() + "\n"
}
if leakCheckPanicEnabled() {
panic(msg)
}
log.Warningf(msg)
}
})
checkOnce.Do(doLeakCheck)
}
}
// DoRepeatedLeakCheck is the same as DoLeakCheck except that it can be called
// multiple times by the caller to incrementally perform leak checking.
func DoRepeatedLeakCheck() {
if leakCheckEnabled() {
doLeakCheck()
}
}
func doLeakCheck() {
liveObjectsMu.Lock()
defer liveObjectsMu.Unlock()
leaked := len(liveObjects)
if leaked > 0 {
msg := fmt.Sprintf("Leak checking detected %d leaked objects:\n", leaked)
for obj := range liveObjects {
msg += obj.LeakMessage() + "\n"
}
if leakCheckPanicEnabled() {
panic(msg)
}
log.Warningf(msg)
}
}
+1
View File
@@ -245,6 +245,7 @@ func (g *Gofer) serveLisafs(spec *specs.Spec, conf *config.Config, root string)
server.StartConnection(conn)
}
server.Wait()
server.Destroy()
log.Infof("All lisafs servers exited.")
return subcommands.ExitSuccess
}