fix(revlog): log fetch errors instead of aborting the process - #3019
Open
MsfPablo wants to merge 1 commit into
Open
fix(revlog): log fetch errors instead of aborting the process#3019MsfPablo wants to merge 1 commit into
MsfPablo wants to merge 1 commit into
Conversation
The unfiltered Log tab spawns a rayon worker that calls
fetch_helper(...).expect("failed to fetch"). When gix discovery
fails the panic happens on a rayon worker thread, and rayon re-aborts
the whole process. The most reachable trigger is the process cwd
being deleted (e.g. stashing untracked files from inside the now-
removed subdirectory): gix discovery reads the process cwd
unconditionally (gix/src/discover.rs::discover_opts sets
options.current_dir from gix_fs::current_dir), so even passing an
absolute repo root does not help, and the git2-based paths that
do not consult the cwd keep working while the unfiltered Log tab
dies.
Replace the .expect with the same error-logging idiom already used
by asyncgit::status, asyncgit::blame and asyncgit::diff: log the
fetch error and let the worker degrade the tab instead of aborting
the process. This addresses the escalation the issue calls out as
worth handling regardless of the cwd question.
Fixes gitui-org#3017
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The unfiltered Log tab spawns a rayon worker that calls
fetch_helper(...).expect(\"failed to fetch\")atasyncgit/src/revlog.rs. When the underlyinggixdiscovery fails, the panic fires on a rayon worker thread and rayon re-aborts the whole process, killing gitui rather than just degrading the tab.This is independent of #3015 (which fixes the git2 half of the same scenario). It addresses the escalation that #3017 explicitly calls out as worth handling regardless of the cwd question.
Fixes #3017.
Root cause
fetch()spawns a rayon worker:fetch_helper_without_filtercallsgix_repo(repo_path), which usesgix::ThreadSafeRepository::discover_with_environment_overrides.gixdiscovery reads the process cwd unconditionally (gix/src/discover.rs::discover_optssetsoptions.current_dirfromgix_fs::current_dir), so even passing an absolute repo root does not help when the process cwd has been deleted. The most reachable trigger is stashing untracked files from inside the now-removed subdirectory (libgit2 removes it;git stash -urefuses this but libgit2 has no such guard). The git2-based paths (repo()viagit2::Repository::open_ext) do not consult the cwd for an absolute path, which is whyget_stashesand the filtered log keep working while the unfiltered Log tab dies.A panic on a rayon worker is not contained to the worker: rayon unwinds it and then re-aborts the process, so the user-visible symptom is gitui disappearing rather than an empty Log tab.
Fix
Replace the
.expect(\"failed to fetch\")with the same error-logging idiom already used byasyncgit::status(asyncgit/src/status.rs),asyncgit::blame(asyncgit/src/blame.rs), andasyncgit::diff(asyncgit/src/diff.rs): log the fetch error and let the worker finish without aborting.This does not change the cwd behaviour of
gixdiscovery; it stops a discovery failure from escalating into a process abort. The Log tab simply shows no new commits for that fetch, which is the behaviour users already see for the git2 paths when the repo is temporarily unreadable.Verification
cargo build -p asyncgit— clean.cargo test -p asyncgit— 175 passed, 2 failed. The 2 failures (sync::sign::tests::test_openpgp_sign_and_verify_e2e,sync::sign::tests::test_x509_sign_and_verify_e2e) are pre-existing and reproduce on the unmodified base (they requiregpg/gpgsmbinaries that are not installed in this environment). Verified by stashing the change and re-running.cargo test -p asyncgit revlog—test_env_variablesandtest_smoke_in_subdirpass.cargo fmt --check -p asyncgit— clean.make clippy(cargo clippy --workspace --all-features, the command CI runs) — clean.Note on regression testing
The panic path lives inside the rayon worker spawned by
fetch(). A panic there is not contained to the worker thread: rayon unwinds it and re-aborts the whole process, which is exactly the bug. This also means a deterministic unit test cannot assert "the worker does not abort" — on the unmodified base the worker panic would abort the entire test binary (including other, unrelated tests), not just the test that triggered it. The lower-levelfetch_helper_without_filterErr path is already covered bytest_env_variablesandtest_smoke_in_subdir(they assert it returnsOkorErrwithout panicking). The change here mirrors the establishedstatus/blame/diffidiom, which is the project's existing answer to the same class of "rayon worker fetch failure" panics.Reproduction of the original abort is documented in the issue body (a scratch crate linking
asyncgit: create a repo, add an untracked subdirectory, set the process cwd inside it,stash_save(..., untracked=true), then callAsyncLog::fetch). After this change the same repro logsfetch_helper revlog: Gix(Discover(Discover(CurrentDir(...))))and gitui stays alive instead of aborting.AI disclosure
This change was prepared with agent assistance. The reproduction evidence is cited from the issue body; the fix mirrors the existing
asyncgit::status/blame/differror-handling idiom. The commands above were run locally to verify build, tests, fmt and clippy.