Documentation ¶
Overview ¶
Package runinhibit contains operations for establishing, removing and querying snap run inhibition lock.
Index ¶
- Variables
- func HintFile(snapName string) string
- func InhibitInfoFile(snapName string, hint Hint) string
- func IsLocked(snapName string, unlocker Unlocker) (Hint, InhibitInfo, error)
- func LockWithHint(snapName string, hint Hint, info InhibitInfo, unlocker Unlocker) error
- func RemoveLockFile(snapName string, unlocker Unlocker) error
- func Unlock(snapName string, unlocker Unlocker) error
- type Hint
- type InhibitInfo
- type Unlocker
Constants ¶
This section is empty.
Variables ¶
var InhibitDir = defaultInhibitDir
InhibitDir is the directory where inhibition files are stored. This value can be changed by calling dirs.SetRootDir.
var WaitWhileInhibited = func(ctx context.Context, snapName string, notInhibited func(ctx context.Context) error, inhibited func(ctx context.Context, hint Hint, inhibitInfo *InhibitInfo) (cont bool, err error), interval time.Duration) (flock *osutil.FileLock, err error) { ticker := newTicker(interval) defer func() { if err != nil && flock != nil { flock.Close() flock = nil } }() for { flock, err = osutil.OpenExistingLockForReading(HintFile(snapName)) if os.IsNotExist(err) { if notInhibited != nil { if err := notInhibited(ctx); err != nil { return nil, err } } return nil, nil } if err != nil { return nil, err } if err := flock.ReadLock(); err != nil { return flock, err } hint, err := hintFromFile(flock.File()) if err != nil { return flock, err } if hint == HintNotInhibited { if notInhibited != nil { if err := notInhibited(ctx); err != nil { return flock, err } } return flock, nil } else { if inhibited != nil { inhibitInfo, err := readInhibitInfo(snapName, hint) if err != nil { return flock, err } cont, err := inhibited(ctx, hint, &inhibitInfo) if err != nil { return flock, err } if cont { return flock, nil } } } flock.Close() select { case <-ctx.Done(): return nil, ctx.Err() case <-ticker.Wait(): } } }
WaitWhileInhibited blocks until snap is not inhibited anymore and then returns a locked hint file lock.
The `inhibited` callback is run if the snap is initially inhibited, otherwise the `notInhibited` callback is run. In either case, this callback runs with the hint file lock held`.
If inhibited callback returns true, WaitWhileInhibited returns instantly without waiting for the snap not being inhibited.
NOTE: A snap without a hint file is considered not inhibited and a nil FileLock is returned.
NOTE: It is the caller's responsibility to release the returned file lock.
Functions ¶
func InhibitInfoFile ¶
func IsLocked ¶
func IsLocked(snapName string, unlocker Unlocker) (Hint, InhibitInfo, error)
IsLocked returns the state of the run inhibition lock for the given snap.
It returns the current, non-empty hint if inhibition is in place. Otherwise it returns an empty hint.
If unlocker is passed it indicates that the global state needs to be unlocked before taking the inhibition hint file lock. It is the responsibility of the caller to make sure state is locked if a non-nil unlocker is passed.
func LockWithHint ¶
func LockWithHint(snapName string, hint Hint, info InhibitInfo, unlocker Unlocker) error
LockWithHint sets a persistent "snap run" inhibition lock, for the given snap, with a given hint and saves given info that will be needed by "snap run" during inhibition (e.g. snap revision).
The hint cannot be empty. It should be one of the Hint constants defined in this package. With the hint in place "snap run" will not allow the snap to start and will block, presenting a user interface if possible. Also info.Previous corresponding to the snap revision that was installed must be provided and cannot be unset.
If unlocker is passed it indicates that the global state needs to be unlocked before taking the inhibition hint file lock. It is the responsibility of the caller to make sure state is locked if a non-nil unlocker is passed.
func RemoveLockFile ¶
RemoveLockFile removes the run inhibition lock for the given snap.
This function should not be used as a substitute of Unlock, as race-free ability to inspect the inhibition state relies on flock(2) which requires the file to exist in the first place and non-privileged processes cannot create it.
The function does not fail if the inhibition lock does not exist.
If unlocker is passed it indicates that the global state needs to be unlocked before taking the inhibition hint file lock. It is the responsibility of the caller to make sure state is locked if a non-nil unlocker is passed.
func Unlock ¶
Unlock truncates the run inhibition lock, for the given snap.
An empty inhibition lock means uninhibited "snap run".
If unlocker is passed it indicates that the global state needs to be unlocked before taking the inhibition hint file lock. It is the responsibility of the caller to make sure state is locked if a non-nil unlocker is passed.
Types ¶
type Hint ¶
type Hint string
Hint is a string representing reason for the inhibition of "snap run".
const ( // HintNotInhibited is used when "snap run" is not inhibited. HintNotInhibited Hint = "" // HintInhibitedGateRefresh represents inhibition of a "snap run" while gate-auto-refresh hook is run. HintInhibitedGateRefresh Hint = "gate-refresh" // HintInhibitedForRefresh represents inhibition of a "snap run" while a refresh change is being performed. HintInhibitedForRefresh Hint = "refresh" // HintInhibitedForPreDownload represents inhibition of a "snap run" while a // pre-download is triggering a refresh. HintInhibitedForPreDownload Hint = "pre-download" // HintInhibitedForRemove represents inhibition of a "snap run" while a remove change is being performed. HintInhibitedForRemove Hint = "remove" )
type InhibitInfo ¶
type InhibitInfo struct { // Previous is the previous revision for the snap being refreshed. Previous snap.Revision `json:"previous"` }
InhibitInfo holds data of the previous snap revision that will be needed by "snap run" while the snap is unlinked (i.e. the current symlink is removed).
type Unlocker ¶
type Unlocker func() (relock func())
Unlocker functions are passed from code using runinhibit to indicate that global state should be unlocked during file lock operations to avoid having deadlocks where both inhibition hint file and state are locked and waiting for each other. Unlocker being nil indicates not to do this.