Skip to content
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

flatpak-dir: Avoid false "changed" notitications for empty installations #5252

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

mcrha
Copy link
Contributor

@mcrha mcrha commented Jan 10, 2023

This is related to downstream bug:
https://gitlab.gnome.org/GNOME/gnome-software/-/issues/1989

The gnome-software could pass an already cancelled GCancellable into the libflatpak functions, which can end at _flatpak_dir_ensure_repo, which unconditionally calls flatpak_dir_mark_changed() to create the .changed file, even when it exists, because the earlier call to g_file_query_exists() returns FALSE also when the repodir GFile exists, but the cancellable is cancelled.

This exhibits the most with empty installations, which have no refs installed nor any remote configured, because (it seems, though I did not check it in the code) the FlatpakDir is freed early when the installation is completely empty (like my --user installation here). Having there at least a remote configured the FlatpakDir is not freed early, thus it's not recreated on demand.

The first commit adds a test to not call flatpak_dir_mark_changed() when the file already exists. The second commit adds checks for the cancelled state of the cancellable, which can stop the function earlier. As it's not assured when exactly the other thread can cancel the cancellable, I added it into multiple places.

One such place, where the FlatpakDir instance is periodically recreated, is when calling flatpak_installation_list_remotes(), as shown in the following backtrace snippet:

	   _flatpak_dir_ensure_repo() at flatpak-dir.c:4096
	   flatpak_dir_maybe_ensure_repo() at flatpak-dir.c:4284
	   flatpak_installation_list_remotes_by_type() at flatpak-installation.c:1263
	   flatpak_installation_list_remotes() at flatpak-installation.c:1312

The false "changed" notifications are wrong for the gnome-software, because there is no granularity on the signal (having a set of flags for "app/remote $ID added/removed/updated" would be a great improvement), the gnome-software simply reloads everything in the GUI, which can take its time and which is pretty bad user experience, but as there's currently no easy way to recognize what precisely changed, then there's no better option either.

When an installation is completely empty, with no refs installed and
with no remotes configured, its corresponding FlatpakDir is created
periodically. That can cause false "changed" notifications for the
installation, due to unconditional call to flatpak_dir_mark_changed(),
which is meant only to create the file, if it does not exist.
…e_repo()

Check multiple times whether the passed in cancellable is not cancelled,
to avoid unneeded work and to catch properly whether a file exists or not,
because the g_file_query_exists() returns FALSE also when the GFile
exists, but the cancellable is cancelled.
/* Create .changed file early to avoid polling non-existing file in monitor */
if (!flatpak_dir_mark_changed (self, &my_error))
if (!g_file_test (g_file_peek_path (changed_file), G_FILE_TEST_IS_REGULAR) &&
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you have a GFile, you can just use g_file_query_exists()

Comment on lines +4068 to +4069
if (g_cancellable_set_error_if_cancelled (cancellable, error))
return FALSE;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand correctly, the sprinkling of the cancellable checks is because this runs in a thread and the cancellable could have been cancelled at any moment. Maybe the first one should explicitly comment this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will say my personal opinion is that each function that takes a GCancellable should have this check at the start of it. For example all of the OStree functions. But I understand the practicality of spreading it out here to make a change in one place.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct. Furthermore, this is only a single place I faced the problem with. To be complete, one might spread the same checking all around the sources, but I did not dare to do it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants