cmd/root, pkg/utils: Split out the code to acquire a file lock
A subsequent commit will use this to give Toolbx containers access to
the certificates from certificate authorities on the host.
This changes the user-visible error message from:
$ toolbox --verbose list
...
DEBU Migrating to newer Podman: failed to create migration lock file
/run/user/1000/toolbox/migrate.lock: open
/run/user/1000/toolbox/migrate.lock: no such file or directory
Error: failed to create migration lock file
... to:
$ toolbox --verbose list
...
DEBU Migrating to newer Podman: failed to create lock file
/run/user/1000/toolbox/migrate.lock: open
/run/user/1000/toolbox/migrate.lock: no such file or directory
Error: failed to create lock file
Or, from:
$ toolbox --verbose list
...
DEBU Migrating to newer Podman: failed to acquire migration lock on
/run/user/1000/toolbox/migrate.lock: bad file descriptor
Error: failed to acquire migration lock
... to:
$ toolbox --verbose list
...
DEBU Migrating to newer Podman: failed to acquire lock on
/run/user/1000/toolbox/migrate.lock: bad file descriptor
Error: failed to acquire lock
This is admittedly less specific without the debug logs, but it's
probably alright because it's such an unlikely error.
https://github.com/containers/toolbox/issues/626
This commit is contained in:
parent
b7be82d51e
commit
456f37794d
|
|
@ -263,21 +263,28 @@ func migrate(cmd *cobra.Command, args []string) error {
|
|||
|
||||
migrateLock := toolboxRuntimeDirectory + "/migrate.lock"
|
||||
|
||||
migrateLockFile, err := os.Create(migrateLock)
|
||||
migrateLockFile, err := utils.Flock(migrateLock, syscall.LOCK_EX)
|
||||
if err != nil {
|
||||
logrus.Debugf("Migrating to newer Podman: failed to create migration lock file %s: %s", migrateLock, err)
|
||||
return errors.New("failed to create migration lock file")
|
||||
logrus.Debugf("Migrating to newer Podman: %s", err)
|
||||
|
||||
var errFlock *utils.FlockError
|
||||
|
||||
if errors.As(err, &errFlock) {
|
||||
if errors.Is(err, utils.ErrFlockAcquire) {
|
||||
err = utils.ErrFlockAcquire
|
||||
} else if errors.Is(err, utils.ErrFlockCreate) {
|
||||
err = utils.ErrFlockCreate
|
||||
} else {
|
||||
panicMsg := fmt.Sprintf("unexpected %T: %s", err, err)
|
||||
panic(panicMsg)
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
defer migrateLockFile.Close()
|
||||
|
||||
migrateLockFD := migrateLockFile.Fd()
|
||||
migrateLockFDInt := int(migrateLockFD)
|
||||
if err := syscall.Flock(migrateLockFDInt, syscall.LOCK_EX); err != nil {
|
||||
logrus.Debugf("Migrating to newer Podman: failed to acquire migration lock on %s: %s", migrateLock, err)
|
||||
return errors.New("failed to acquire migration lock")
|
||||
}
|
||||
|
||||
stampBytes, err := ioutil.ReadFile(stampPath)
|
||||
if err != nil {
|
||||
if !errors.Is(err, os.ErrNotExist) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright © 2022 – 2024 Red Hat Inc.
|
||||
* Copyright © 2022 – 2025 Red Hat Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -31,6 +31,12 @@ type DistroError struct {
|
|||
Err error
|
||||
}
|
||||
|
||||
type FlockError struct {
|
||||
Path string
|
||||
Errs []error
|
||||
errSuffix string
|
||||
}
|
||||
|
||||
type ImageError struct {
|
||||
Image string
|
||||
Err error
|
||||
|
|
@ -58,6 +64,25 @@ func (err *DistroError) Unwrap() error {
|
|||
return err.Err
|
||||
}
|
||||
|
||||
func (err *FlockError) Error() string {
|
||||
if err.Errs == nil || len(err.Errs) != 2 {
|
||||
panicMsg := fmt.Sprintf("invalid %T", err)
|
||||
panic(panicMsg)
|
||||
}
|
||||
|
||||
errSuffix := " "
|
||||
if err.errSuffix != "" {
|
||||
errSuffix = fmt.Sprintf(" %s ", err.errSuffix)
|
||||
}
|
||||
|
||||
errMsg := fmt.Sprintf("%s%s%s: %s", err.Errs[0], errSuffix, err.Path, err.Errs[1])
|
||||
return errMsg
|
||||
}
|
||||
|
||||
func (err *FlockError) Unwrap() []error {
|
||||
return err.Errs
|
||||
}
|
||||
|
||||
func (err *ImageError) Error() string {
|
||||
errMsg := fmt.Sprintf("%s: %s", err.Image, err.Err)
|
||||
return errMsg
|
||||
|
|
|
|||
|
|
@ -164,6 +164,10 @@ var (
|
|||
|
||||
ErrDistroWithoutRelease = errors.New("non-default distribution must specify release")
|
||||
|
||||
ErrFlockAcquire = errors.New("failed to acquire lock")
|
||||
|
||||
ErrFlockCreate = errors.New("failed to create lock file")
|
||||
|
||||
ErrImageWithoutBasename = errors.New("image does not have a basename")
|
||||
)
|
||||
|
||||
|
|
@ -227,6 +231,23 @@ func EnsureXdgRuntimeDirIsSet(uid int) {
|
|||
}
|
||||
}
|
||||
|
||||
func Flock(path string, how int) (*os.File, error) {
|
||||
file, err := os.Create(path)
|
||||
if err != nil {
|
||||
errs := []error{ErrFlockCreate, err}
|
||||
return nil, &FlockError{Path: path, Errs: errs}
|
||||
}
|
||||
|
||||
fd := file.Fd()
|
||||
fdInt := int(fd)
|
||||
if err := syscall.Flock(fdInt, how); err != nil {
|
||||
errs := []error{ErrFlockAcquire, err}
|
||||
return nil, &FlockError{Path: path, Errs: errs, errSuffix: "on"}
|
||||
}
|
||||
|
||||
return file, nil
|
||||
}
|
||||
|
||||
func ForwardToHost() (int, error) {
|
||||
envOptions := GetEnvOptionsForPreservedVariables()
|
||||
toolboxPath := os.Getenv("TOOLBOX_PATH")
|
||||
|
|
|
|||
Loading…
Reference in New Issue