Move lock init after tmp dir is populated properly

Don't initialize the lock manager until almost the end of libpod
init, so we can guarantee our tmp dir is properly set up and
exists. This wasn't an issue on systems that had previously run
Podman, but CI caught it.

Signed-off-by: Matthew Heon <matthew.heon@pm.me>
This commit is contained in:
Matthew Heon
2019-01-03 16:09:37 -05:00
parent 01858c0eba
commit 97681a5f2b
2 changed files with 59 additions and 58 deletions

View File

@ -499,64 +499,6 @@ func makeRuntime(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 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()
locked := true
doRefresh := false
defer func() {
if locked {
aliveLock.Unlock()
}
}()
_, err = os.Stat(runtimeAliveFile)
if err != nil {
// If the file doesn't exist, we need to refresh the state
// This will trigger on first use as well, but refreshing an
// empty state only creates a single file
// As such, it's not really a performance concern
if os.IsNotExist(err) {
doRefresh = true
} else {
return errors.Wrapf(err, "error reading runtime status file %s", runtimeAliveFile)
}
}
// Set up the lock manager
var manager lock.Manager
lockPath := DefaultSHMLockPath
if rootless.IsRootless() {
lockPath = DefaultRootlessSHMLockPath
}
if doRefresh {
// If SHM locks already exist, delete them and reinitialize
if err := os.Remove(filepath.Join("/dev/shm", lockPath)); err != nil && !os.IsNotExist(err) {
return errors.Wrapf(err, "error deleting existing libpod SHM segment %s", lockPath)
}
manager, err = lock.NewSHMLockManager(lockPath, runtime.config.NumLocks)
if err != nil {
return errors.Wrapf(err, "error creating SHM locks for libpod")
}
} else {
manager, err = lock.OpenSHMLockManager(lockPath, runtime.config.NumLocks)
if err != nil {
return errors.Wrapf(err, "error opening libpod SHM locks")
}
}
runtime.lockManager = manager
// Set up the state
switch runtime.config.StateType {
case InMemoryStateStore:
@ -715,6 +657,64 @@ func makeRuntime(runtime *Runtime) (err error) {
}
runtime.firewallBackend = fwBackend
// 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 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()
locked := true
doRefresh := false
defer func() {
if locked {
aliveLock.Unlock()
}
}()
_, err = os.Stat(runtimeAliveFile)
if err != nil {
// If the file doesn't exist, we need to refresh the state
// This will trigger on first use as well, but refreshing an
// empty state only creates a single file
// As such, it's not really a performance concern
if os.IsNotExist(err) {
doRefresh = true
} else {
return errors.Wrapf(err, "error reading runtime status file %s", runtimeAliveFile)
}
}
// Set up the lock manager
var manager lock.Manager
lockPath := DefaultSHMLockPath
if rootless.IsRootless() {
lockPath = DefaultRootlessSHMLockPath
}
if doRefresh {
// If SHM locks already exist, delete them and reinitialize
if err := os.Remove(filepath.Join("/dev/shm", lockPath)); err != nil && !os.IsNotExist(err) {
return errors.Wrapf(err, "error deleting existing libpod SHM segment %s", lockPath)
}
manager, err = lock.NewSHMLockManager(lockPath, runtime.config.NumLocks)
if err != nil {
return errors.Wrapf(err, "error creating SHM locks for libpod")
}
} else {
manager, err = lock.OpenSHMLockManager(lockPath, runtime.config.NumLocks)
if err != nil {
return errors.Wrapf(err, "error opening libpod SHM locks")
}
}
runtime.lockManager = manager
// If we need to refresh the state, do it now - things are guaranteed to
// be set up by now.
if doRefresh {

View File

@ -82,6 +82,7 @@ func (r *Runtime) newContainer(ctx context.Context, rSpec *spec.Spec, options ..
}
ctr.lock = lock
ctr.config.LockID = ctr.lock.ID()
logrus.Debugf("Allocated lock %d for container %s", ctr.lock.ID(), ctr.ID())
ctr.valid = true
ctr.state.State = ContainerStateConfigured