mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Enable reference count leak checking for lisafs.
Also add DoRepeatedLeakCheck() to refsvfs2 package. Updates #5466 PiperOrigin-RevId: 425004987
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user