diff options
author | Matthew Heon <matthew.heon@gmail.com> | 2017-12-04 14:44:03 -0500 |
---|---|---|
committer | Matthew Heon <matthew.heon@gmail.com> | 2017-12-04 14:45:49 -0500 |
commit | 92bc448624e29fc84087bafcccd0e52b328a53e4 (patch) | |
tree | 93daf65340a091c4ac6851dac9dec40219a25abf | |
parent | ae5aac50aaacbdcc20e622e86f40c02136690fe7 (diff) | |
download | podman-92bc448624e29fc84087bafcccd0e52b328a53e4.tar.gz podman-92bc448624e29fc84087bafcccd0e52b328a53e4.tar.bz2 podman-92bc448624e29fc84087bafcccd0e52b328a53e4.zip |
Fix potential race condition in initializing libpod
Signed-off-by: Matthew Heon <matthew.heon@gmail.com>
-rw-r--r-- | libpod/container.go | 2 | ||||
-rw-r--r-- | libpod/runtime.go | 15 |
2 files changed, 13 insertions, 4 deletions
diff --git a/libpod/container.go b/libpod/container.go index e1b002548..c53184ea3 100644 --- a/libpod/container.go +++ b/libpod/container.go @@ -413,7 +413,7 @@ func (c *Container) refresh() error { defer c.lock.Unlock() if !c.valid { - return errors.Wrapf(ErrCtrRemoved, "container %s has been removed from the state", c.ID()) + return errors.Wrapf(ErrCtrRemoved, "container %s is not valid - may have been removed", c.ID()) } // We need to get the container's temporary directory from c/storage diff --git a/libpod/runtime.go b/libpod/runtime.go index 7997679e2..103faf3f8 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -175,7 +175,19 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) { // We now need to see if the system has restarted // We check for the presence of a file in our tmp directory to verify this + // This check must be locked to prevent races + runtimeAliveLock := filepath.Join(runtime.config.TmpDir, "alive.lck") runtimeAliveFile := filepath.Join(runtime.config.TmpDir, "alive") + aliveLock, err := storage.GetLockfile(runtimeAliveLock) + if err != nil { + return nil, errors.Wrapf(err, "error acquiring runtime init lock") + } + // Acquire the lock and hold it until we return + // This ensures that no two processes will be in runtime.refresh at once + // TODO: we can't close the FD in this lock, so we should keep it around + // and use it to lock important operations + aliveLock.Lock() + defer aliveLock.Unlock() _, err = os.Stat(runtimeAliveFile) if err != nil { // If the file doesn't exist, we need to refresh the state @@ -260,9 +272,6 @@ func (r *Runtime) Shutdown(force bool) error { // Reconfigures the runtime after a reboot // Refreshes the state, recreating temporary files // Does not check validity as the runtime is not valid until after this has run -// TODO: there's a potential race here, where multiple libpods could be in this -// function before the runtime ready file is created -// This probably doesn't matter as the actual container operations are locked func (r *Runtime) refresh(alivePath string) error { // We need to refresh the state of all containers ctrs, err := r.state.AllContainers() |