Hello everyone. I’d like to post a small update to aid discussing another chunk of work related to this feature.
Context
Currently snapd performs two checks, dubbed the soft and hard checks, as it performs a refresh of a particular snap. Both checks look at the processes associated with the snap being refreshed but differ in how they decide if the check succeeded or not.
The soft check fails if there are any applications or hooks running. Services are ignored as they are normally stopped later in the refresh process. This check catches the simple instance of an application being open.
The hard check is more strict as it runs after services have been stopped. At this time presence of any application process is a problem as snapd is about to create a copy of the snap data directory and the running application can affect the process.
That’s the current state, now for the new component.
Run inhibition lock
I’d like to introduce a new mechanism, called the run inhibition lock. The lock is scoped to a particular snap and is persistent across reboots. Once held the lock causes snap run
to pause and wait for the lock to be released. While waiting the user is notified that a snap is being refreshed with either a graphical information dialog or directly in the console (if a tty exists).
The lock file is /var/lib/snapd/inhibit/$SNAP_NAME.lock
. Unlike the snap lock, which is stored in /run/snapd/lock/$SNAP_NAME.lock
, the file may exist for arbitrary amount of time The snap lock is ephemeral and has a hard limit of being locked for several seconds only.
The lock files are created and removed by snapd
and read by snap run
.
Hint
The inhibition lock may be empty or may contain a hint. The hint exist to communicate, without having to talk to snapd, why the lock exists. Currently the only value that is defined is the word refresh
, which indicates that snapd is performing a refresh operation that affects this snap.
Empty hint indicates that snap execution is uninhibited.
Non-empty hint indicates that snap execution is inhibited.
Expected usage
I wrote a prototype that grabs the run inhibition lock during the snap-unlink
task and removes it during the snap-link
task. This is technically correct, as the snap cannot be used during that window. I’d like to expand the lock region to start immediately during the soft check mentioned above. While the snap lock is still held. This would allow snapd to detect that a refresh is possible and that it will be possible by the time the hard check is performed.
Inhibition lock operations
The lock files are stored in /var/lib/snapd/inhibit/$SNAP_NAME.lock
.
LockAndSetHint
- open the lock file as 0644
- obtain an exclusive lock (
LOCK_EX
)
- write the hint content
- close the file.
Unlock
- open the lock file
- obtain an exclusive lock
- truncate the file
- close the file
IsLocked
- open the lock file - if missing return informing the lock is not held
- obtain a shared lock (
LOCK_SH
)
- stat the file - if empty then close and return informing the lock is not held
- read the contents and return informing the lock is held and the hint is the read value
- close the file