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"
|
migrateLock := toolboxRuntimeDirectory + "/migrate.lock"
|
||||||
|
|
||||||
migrateLockFile, err := os.Create(migrateLock)
|
migrateLockFile, err := utils.Flock(migrateLock, syscall.LOCK_EX)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Debugf("Migrating to newer Podman: failed to create migration lock file %s: %s", migrateLock, err)
|
logrus.Debugf("Migrating to newer Podman: %s", err)
|
||||||
return errors.New("failed to create migration lock file")
|
|
||||||
|
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()
|
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)
|
stampBytes, err := ioutil.ReadFile(stampPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !errors.Is(err, os.ErrNotExist) {
|
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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -31,6 +31,12 @@ type DistroError struct {
|
||||||
Err error
|
Err error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type FlockError struct {
|
||||||
|
Path string
|
||||||
|
Errs []error
|
||||||
|
errSuffix string
|
||||||
|
}
|
||||||
|
|
||||||
type ImageError struct {
|
type ImageError struct {
|
||||||
Image string
|
Image string
|
||||||
Err error
|
Err error
|
||||||
|
|
@ -58,6 +64,25 @@ func (err *DistroError) Unwrap() error {
|
||||||
return err.Err
|
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 {
|
func (err *ImageError) Error() string {
|
||||||
errMsg := fmt.Sprintf("%s: %s", err.Image, err.Err)
|
errMsg := fmt.Sprintf("%s: %s", err.Image, err.Err)
|
||||||
return errMsg
|
return errMsg
|
||||||
|
|
|
||||||
|
|
@ -164,6 +164,10 @@ var (
|
||||||
|
|
||||||
ErrDistroWithoutRelease = errors.New("non-default distribution must specify release")
|
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")
|
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) {
|
func ForwardToHost() (int, error) {
|
||||||
envOptions := GetEnvOptionsForPreservedVariables()
|
envOptions := GetEnvOptionsForPreservedVariables()
|
||||||
toolboxPath := os.Getenv("TOOLBOX_PATH")
|
toolboxPath := os.Getenv("TOOLBOX_PATH")
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue