-
Notifications
You must be signed in to change notification settings - Fork 125
Lock from the time system repository is loaded until exit #2519
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Lock from the time system repository is loaded until exit #2519
Conversation
Blocks until the lock is acquired, and prints a table to stderr listing the other processes we're waiting for: $ sudo dnf5 install rsms-inter-fonts Waiting for other processes to finish: 62409 dnf5 install blender For now, always acquire a write lock. In the future, we could perhaps add a way to tell the context whether write operations are allowed. See also cmd_requires_privileges.
Add a new flag to Context to set whether we plan on modifying the system repo. If will_modify_system is false, then Context::load_repos will acquire a READ lock on the system repository before loading it. If will_modify_system is true (the default), then a WRITE lock will be acquired.
|
Now the non-privileged commands acquire a READ lock, not a WRITE lock. I'm still trying to figure out how this should work for unprivileged users. If a root DNF process has not yet created Maybe we could put it in We'd also need to extend |
We want the system-repo.lock to be persisted on the filesystem so that unprivileged users can acquire a read lock on it without needing the permissions to create it. This is an ABI-breaking change, so this commit also bumps the version to 5.4.0.0.
Moves system-repo.lock from /run/dnf/system-repo.lock to /usr/lib/sysimage/libdnf5/system-repo.lock and makes it persistent and provided by libdnf5. This way, the file can always be owned by root and other unprivileged users can open it for reading and obtain a read lock without needing permissions to create the file. Also adds Base::get_system_repo_lock() to get a pointer to the Locker instance and renames LockAccessType to LockAccess and LockBlockingType to LockBlocking.
|
I've moved the lockfile to Now I think we just need some flag to ignore the locks in the case where e.g. a privileged user doesn't care about an unprivileged user's read lock on the system repo. |
The option is called "skip_system_repo_lock" as opposed to "ignore_system_repo_lock" since we don't even try to acquire a lock if skip_system_repo_lock is enabled. This way, the option is useful for situations where the unprivileged user may not have permissions to create the lockfile, e.g. in a root-owned installroot that does not contain /usr/lib/sysimage/libdnf5/system-repo.lock.
This is an API-breaking change. This way we can use Context::load_repos even when available repositories are not needed, instead of using RepoSack::load_repos. Context::load_repos has the logic for locking the system repo.
|
I think this is in a good place for initial review. I ended up making an API-breaking change to add a |
kontura
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While I don't think these breaking changes will actually break anyone's code I am not thrilled about bumping the major version so soon again.
I think we could get around it by rather introducing new API but I am not sure if there is any real technical reason for this.
|
|
||
| bool load_system_repo{false}; | ||
| LoadAvailableRepos load_available_repos{LoadAvailableRepos::NONE}; | ||
| bool will_modify_system{true}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I understand correctly this value is derived from (it duplicates) information already present in the Context. Is there a plan to use it somehow differently later on?
Currently I would rather make cmd_requires_privileges(dnf5::Context context) a private method of Context and use it directly. It would require introducing a private header file for Context, where we would likely move Context::Impl, but I think that would be a good move regardless.
What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It may be useful in the future for commands (especially those provided by plugins) to declare for themselves whether they will modify the system rather than doing the heuristics in cmd_requires_privileges. Also if we ever do something about https://issues.redhat.com/browse/RHEL-67915, there would be a distinction between "will modify the system repository" (inside the installroot) and "needs root privileges".
But for now your suggestion is maybe better, like you said, a context_private.hpp would be a good idea.
|
|
||
| /// Sets callbacks for repositories and loads them, updating metadata if necessary. | ||
| void load_repos(bool load_system); | ||
| void load_repos(bool load_system, bool load_available); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While we are doing changes here, I am wondering whether the Context.load_repos(...) API should be public at all. If I am not mistaken this API is for dnf5 plugins and those will already be using it through the dnf5 main function.
I see it is now used in makecache command but that feels more like an oversight to me because it results in calling it twice. I believe it could easily be removed.
This would need a private header for Context as welll though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, it could be made private.
Most of the ABI/API changes are in |
Related: #2129
This is another step towards proper locking so that multiple DNF5 processes don't interfere with each other.
Adds
Base::lock_system_repoandBase::unlock_system_repo:And calls
Base::lock_system_repofromContext::load_reposbefore the system repo is loaded.The idea here is that we need to hold a lock the entire time from before the transaction is resolved until after the transaction is complete and the RPMDB is written. Otherwise, another DNF process could resolve a transaction using a soon-to-be-invalid version of the system repo and get an invalid transaction.
This approach is an improvement over DNF4 which blocks while another transaction is running but does not block before loading the system repo and resolving a new transaction.
A helpful message is printed listing the other processes DNF5 is waiting for: