-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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
race: completion: Top layer ... not found ... storage may be corrupted #23331
race: completion: Top layer ... not found ... storage may be corrupted #23331
Comments
To be clear I don't think any of the races are related to completion at all. It just happens that the shell completion test has to do a ton of listing (podman ps, podman images,...) in a long loop so it is super likely to catch races there. Seems to related to db37d66 |
And I must say the suggestion of |
diff --git a/test/system/010-images.bats b/test/system/010-images.bats
index 1548615a7..3653d242d 100644
--- a/test/system/010-images.bats
+++ b/test/system/010-images.bats
@@ -394,7 +394,7 @@ EOF
@test "podman images with concurrent removal" {
skip_if_remote "following test is not supported for remote clients"
- local count=5
+ local count=100
# First build $count images
for i in $(seq --format '%02g' 1 $count); do
@@ -411,21 +411,9 @@ EOF
for i in $(seq --format '%02g' 1 $count); do
timeout --foreground -v --kill=10 60 \
$PODMAN rmi i$i &
+ run_podman images --format "{{.ID}} {{.Names}}"
done
- tries=100
- while [[ ${#lines[*]} -gt 1 ]] && [[ $tries -gt 0 ]]; do
- # Prior to #18980, 'podman images' during rmi could fail with 'image not known'
- # '0+w' because we sometimes get warnings.
- run_podman 0+w images --format "{{.ID}} {{.Names}}"
- allow_warnings "Top layer .* of image .* not found in layer tree"
- tries=$((tries - 1))
- done
-
- if [[ $tries -eq 0 ]]; then
- die "Timed out waiting for images to be removed"
- fi
-
wait
} then run with |
Ok so the libimage code is racy by design. First the code gets a list of all images[1], then it tries to build a layer tree[2] and for that must get a list of all layers[3]. [2] https://github.com/containers/common/blob/fdbae3a180cb1d81cb4316e0077b3906672c75a8/libimage/runtime.go#L611 I don't see any way to fix this. We could just stop throwing this bogus warning but I assume it was added for a reason in cases where the store is actually corrupt and we have a image without layer... (is that even possible with the c/storage locking mechanism?) I guess ideally we would get all images and layers in one locked c/storage call, i.e. something like |
Yes.
It shouldn’t be possible: deleting a layer verifies that there are no references to it (in particular no But bugs happen, and I think if the storage were corrupt, the user should be told something to allow diagnosing inexplicably missing images.
Yes, I think that would make sense. (Also note the
I think qualifying this with “if there are no concurrent container operations happening, …” is the least we should do. I don’t have a strong opinion on silencing the warning completely — my weak preference would be to keep it for user-initiated operations, but to be silent for command completion. Maybe command completion should silence warnings universally; I’m not at all sure. |
We recently merged
I would like this because we can then clearly assume the store is inconsistent if we hit this condition.
Note this is not related to shell completion at all, the test reverse engineers how shell completion works via the cobra library by manually calling the hidden completion command. All stderr lines of the command are ignored and never seen when actually uses shell completion interactively so this is already the case. In general the shell completion test has found a lot of issues because it essentially does the listing over and over for all our commands and other tests do other stuff in parallel now. |
Nice, yes.
Thanks, I didn’t know that. |
Oops, this is the hard part. So we would probably not touch |
@vrothberg FYI |
podman system reset nukes everything which makes not a great suggestion. Now that we have the podman system check recommend that instead as it actually checks the storage for corruption and might be able to repair it. This is important because as it turns out this warning can pop up even in totally normal circumstances as there is a race between image and layer listing[1]. And even if that get fixed the check command will be the better suggestion. [1] containers/podman#23331 Signed-off-by: Paul Holzinger <pholzing@redhat.com>
Slightly different symptom seen rawhide rootless:
I'm treating it as a different manifestation of this same bug. |
Yes I think that is fundamentally the same race issue between listing two times, however this one might be even harder fix... |
Another new symptom that I'm assigning here, seen in debian root:
|
Implementation note for c/storage: add a new method to the |
Would it sense to add a more generic function i.e.
and then we only populate the result based on what was requested in the options? |
I’m very weakly opposed, but I wouldn’t reject a PR of that kind. (I’m more dubious about the concept of wanting to add more options than an API with exactly these three fields.) Conceptually, c/storage locks are (not measured, intuitively) quite expensive and it might be an Interesting Project to try to decrease the number of times we take them. Preferably we would want to hold them for short periods, i.e. quickly getting a snapshot of data under a lock, and then computing LayerTree / history can be done without the lock. OTOH the ultimate consumer might only care about one or two fields, so getting a full Pragmatically, I think the main obstacle is actually going to be the abstraction barriers in the callers anyway — IIRC there are various places in [And then there’s the dream of a single c/storage+Podman database, maybe Sqlite, with a single set of locks? I don’t know how we could get there.] Imagining the implementation, the code structure doing the right kind of locking for these three bools would be a little complex but certainly very manageable. But to the extent this anticipates adding more kinds of objects to query, ones that might require taking specific combinations of locks (“the user asked for StorageChar”, so we need to take the containers+layers lock”), I think it the universal Either way, the callers are blocked on adding a c/storage PR and rebasing c/storage, and to me that’s the larger hurdle than what are the exact details of the PR. But then again, there might very well be at least a single caller which currently lists images+layers+containers in sequence and expects the data to be consistent; if we had that single caller call the proposed new |
Maybe, if we assume we only want images + layers then yes one function for that is simple. But if we have other callers that maybe want containers, images and layers then we have to add another again, then another callers wants containers and images and so on. Thus my suggestion of something more generic. If we know this is unlikely to happen (I don't know that) then sure let's opt for the simple fix for the issue at hand. To me the Regardless the storage part is seems to me like the easy part, fixing c/common callers is harder as one must audit all code paths for such races. |
TL;DR: Very generally speaking, I’m not worried about the number of functions. I find it easier to evolve APIs that have many operations, each for a very specific purpose (“what is the size of the image on disk, counting shared data and image-specific data separately”?) than APIs that have a small surface and give the user everything (“inspect an image, I will then read the fields I care about”), primarily because for the specific APIs, we know exactly what the caller wants, we can find the callers (maybe there aren’t any any more), and we have much more freedom to change the underlying implementation. The general APIs are simpler to write, and maybe compose better for a bit, but the “everything” concept means that users end up hard-coding assumptions about the designs and relationships that can never be changed later. Of course there is a balance to be struck, users do need some way to inspect actual system state down to possible implementation details — but on balance, I am biased towards many specific APIs (whether that’s functions/objects/fields) with limited purpose and limited promises; and I’m willing to pay the price of more symbols and longer names. E.g. the whole |
Changes need to be propagated to Podman. |
@Honny1 You can open a PR here to update to c/common@main so we can get this race fixed for @edsantiago's parallel test work. |
@Luap99 I'm going for it. |
@Luap99 Should I vendor it in other projects? If so, which ones? |
|
@Honny1 More importantly, the c/common work changes c/common API — so please prepare PRs to update all users, to avoid a later unexpected surprise. |
Here is PR vendoring for Buildah: containers/buildah#5710 |
This commit vendor pre-release version of `c/common:8483ef6022b4`. It also adapts the code to the new `c/common/libimage` API, which fixes an image listing race that was listing false warnings. fixes: containers#23331 Signed-off-by: Jan Rodák <hony.com@seznam.cz>
Another parallel-system-test flake in command completion, seen in f39 rootless:
I haven't tried to look for a reproducer yet.
The text was updated successfully, but these errors were encountered: