diff options
author | Dean Deng <deandeng@google.com> | 2020-08-10 10:31:27 -0700 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2020-08-10 10:33:22 -0700 |
commit | 79e7d0b06ac019e3c302e2ab9c5861311304d7d1 (patch) | |
tree | f446279a6f69206b7c473b7b51a6efa1befcc14c | |
parent | b404b5c255214a37d7f787f9fe24bb8e22509eb4 (diff) |
Run GC before sandbox exit when leak checking is enabled.
Running garbage collection enqueues all finalizers, which are used by the
refs/refs_vfs2 packages to detect reference leaks. Note that even with GC,
there is no guarantee that all finalizers will be run before the program exits.
This is a best effort attempt to activate leak checks as much as possible.
Updates #3545.
PiperOrigin-RevId: 325834438
-rw-r--r-- | pkg/refs/refcounter.go | 10 | ||||
-rw-r--r-- | runsc/boot/loader.go | 3 |
2 files changed, 13 insertions, 0 deletions
diff --git a/pkg/refs/refcounter.go b/pkg/refs/refcounter.go index 3f39edb66..d9d5e6bcb 100644 --- a/pkg/refs/refcounter.go +++ b/pkg/refs/refcounter.go @@ -475,3 +475,13 @@ func (r *AtomicRefCount) DecRefWithDestructor(ctx context.Context, destroy func( func (r *AtomicRefCount) DecRef(ctx context.Context) { r.DecRefWithDestructor(ctx, nil) } + +// OnExit is called on sandbox exit. It runs GC to enqueue refcount finalizers, +// which check for reference leaks. There is no way to guarantee that every +// finalizer will run before exiting, but this at least ensures that they will +// be discovered/enqueued by GC. +func OnExit() { + if LeakMode(atomic.LoadUint32(&leakMode)) != NoLeakChecking { + runtime.GC() + } +} diff --git a/runsc/boot/loader.go b/runsc/boot/loader.go index 533b9c5e7..40c6f99fd 100644 --- a/runsc/boot/loader.go +++ b/runsc/boot/loader.go @@ -32,6 +32,7 @@ import ( "gvisor.dev/gvisor/pkg/log" "gvisor.dev/gvisor/pkg/memutil" "gvisor.dev/gvisor/pkg/rand" + "gvisor.dev/gvisor/pkg/refs" "gvisor.dev/gvisor/pkg/sentry/arch" "gvisor.dev/gvisor/pkg/sentry/control" "gvisor.dev/gvisor/pkg/sentry/fdimport" @@ -1011,6 +1012,8 @@ func (l *Loader) WaitExit() kernel.ExitStatus { // Cleanup l.ctrl.stop() + refs.OnExit() + return l.k.GlobalInit().ExitStatus() } |