Skip to content

maintenance(geometric): avoid deadlocks on Windows 10#2103

Open
dscho wants to merge 2 commits intogitgitgadget:masterfrom
dscho:avoid-deadlocks-in-geometric-repacking-on-windows
Open

maintenance(geometric): avoid deadlocks on Windows 10#2103
dscho wants to merge 2 commits intogitgitgadget:masterfrom
dscho:avoid-deadlocks-in-geometric-repacking-on-windows

Conversation

@dscho
Copy link
Copy Markdown
Member

@dscho dscho commented Apr 28, 2026

On Windows, maintenance_task_geometric_repack() opens pack index files via pack_geometry_init() (which mmap()s the .idx files), then spawns git repack as a child process without setting child.odb_to_close. The parent's mmap()s prevent the child from deleting old .idx files.

On Windows 10 builds before the POSIX delete semantics change (between Build 17134.1304 and 18363.657, see https://stackoverflow.com/a/60512798), this results in Unlink of file '.git/objects/pack/pack-<hash>.idx' failed. Should I try again? during fetch-triggered auto-maintenance with the geometric strategy.

The fix adds the missing child.odb_to_close = the_repository->objects line, matching all other maintenance tasks.

The first commit introduces a GIT_TEST_LEGACY_DELETE environment variable to simulate legacy (pre-POSIX) delete semantics on modern Windows, so the regression test can verify the fix even on Windows 11.

This fixes git-for-windows#6210.

At some point between Windows 10 Build 17134.1304 and Build 18363.657,
the default behavior of `DeleteFileW()` was changed to use POSIX
semantics (https://stackoverflow.com/a/60512798). Under those semantics,
a file can be deleted even when another process holds an active
`MapViewOfFile` view on it: the directory entry is removed immediately,
but the underlying data persists until the last handle is closed.

On older Windows versions (and Windows 10 builds before that change),
`DeleteFileW()` uses legacy semantics where deletion fails outright if
any process holds a file mapping.

To allow testing code paths that depend on the legacy behavior, introduce
a `GIT_TEST_LEGACY_DELETE` environment variable. When set, `mingw_unlink()`
uses `SetFileInformationByHandle()` with `FileDispositionInfo` (the
non-POSIX variant) instead of `DeleteFileW()`, forcing legacy delete
semantics regardless of the Windows version.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
@dscho dscho changed the title maintenance(geometric): avoid deadlocks on Windows maintenance(geometric): avoid deadlocks on Windows 10 Apr 28, 2026
@dscho dscho self-assigned this Apr 28, 2026
As is done for all the other maintenance tasks, let's release the ODB
also before starting the geometric repacking. That way, the `.idx` files
won't be `mmap()`ed when they are to be deleted (which does not work on
Windows because you cannot delete files on that platform as long as they
are kept open by a process).

This regression was introduced by 9bc1518 (builtin/maintenance:
introduce "geometric-repack" task, 2025-10-24), but was only noticed
once geometric repacking was made the default in 452b12c (builtin/
maintenance: use "geometric" strategy by default, 2026-02-24).

The fix recapitulates my work from df76ee7 (run-command: offer to
close the object store before running, 2021-09-09) & friends.

To guard against future regressions of this kind, add a check to
`run_and_verify_geometric_pack()` in `t7900` that detects orphaned
`.idx` files left behind after repacking. Contrary to interactive
calls, the `git maintenance` call in that test case would _not_ block on
Windows, asking whether to retry deleting that file, which is the reason
why this bug was not caught earlier.

Furthermore, since the default behavior of `DeleteFileW()` was changed
at some point between Windows 10 Build 17134.1304 and Build 18363.657
to use POSIX semantics (see https://stackoverflow.com/a/60512798),
the added orphaned-`.idx` check would be insufficient to catch this
regression on modern Windows without emulating legacy delete semantics
via `GIT_TEST_LEGACY_DELETE=1`.

This fixes git-for-windows#6210.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
@dscho dscho force-pushed the avoid-deadlocks-in-geometric-repacking-on-windows branch from 47c2b34 to 12ebd5c Compare April 28, 2026 00:49
@dscho dscho marked this pull request as ready for review April 28, 2026 06:24
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.

Regression in Git for Windows 2.54: fetch-triggered auto maintenance fails to unlink .git/objects/pack/*.idx with geometric maintenance

1 participant