AsyncBarrier should be run after all defers in destroyContainerFS.

destroyContainerFS must wait for all async operations to finish before
returning. In an attempt to do this, we call fs.AsyncBarrier() at the end of
the function. However, there are many defer'd DecRefs which end up running
AFTER the AsyncBarrier() call.

This CL fixes this by calling fs.AsyncBarrier() in the first defer statement,
thus ensuring that it runs at the end of the function, after all other defers.

PiperOrigin-RevId: 220523545
Change-Id: I5e96ee9ea6d86eeab788ff964484c50ef7f64a2f
This commit is contained in:
Nicolas Lacasse 2018-11-07 13:54:47 -08:00 committed by Shentubot
parent c92b9b7086
commit 13b48f2e6a
1 changed files with 13 additions and 7 deletions

View File

@ -638,6 +638,19 @@ func setExecutablePath(ctx context.Context, mns *fs.MountNamespace, procArgs *ke
// destroyContainerFS cleans up the filesystem by unmounting all mounts for the
// given container and deleting the container root directory.
func destroyContainerFS(ctx context.Context, cid string, k *kernel.Kernel) error {
defer func() {
// Flushing dirent references triggers many async close
// operations. We must wait for those to complete before
// returning, otherwise the caller may kill the gofer before
// they complete, causing a cascade of failing RPCs.
//
// This must take place in the first deferred function, so that
// it runs after all the other deferred DecRef() calls in this
// function.
log.Infof("Waiting for async filesystem operations to complete")
fs.AsyncBarrier()
}()
// First get a reference to the container root directory.
mns := k.RootMountNamespace()
mnsRoot := mns.Root()
@ -687,12 +700,5 @@ func destroyContainerFS(ctx context.Context, cid string, k *kernel.Kernel) error
return fmt.Errorf("error removing directory %q: %v", containerRoot, err)
}
// Flushing dirent references triggers many async close operations. We
// must wait for those to complete before returning, otherwise the
// caller may kill the gofer before they complete, causing a cascade of
// failing RPCs.
log.Infof("Waiting for async filesystem operations to complete")
fs.AsyncBarrier()
return nil
}