-
Notifications
You must be signed in to change notification settings - Fork 94
Description
Version
v7.4.0.202509020913-r
Operating System
MacOS, Linux
Bug description
When performing a forced fetch operation using FetchProcess.execute(), the fetch is supposed to lock the local ref until the fetch completes.
Locking the local ref is paramount because it would risk losing or overwriting any ref updates that occur locally whilst the fetch operation is in progress.
For detecting local modifications since the start of the fetch, the FetchProcess.want() reads the local ref at the time of the fetch and stores it into the expected object ID of the ref-update.
The ref-update upon completion checks whether the local ref has changed and, if so, returns a LOCK_FAILURE error, aborting the operation.
Actual behavior
- Start a
FetchProcess.execute()of a remote refrefs/heads/remotefoo(value=2) into a local refrefs/heads/localfoo(value=1) - Update the local ref
refs/heads/localfooo(value=3) - Wait for the
FetchProcess.execute()to finish
What I see is that depending on when step 2. happens in the middle of the FetchProcess.execute(), the FetchProcess.execute() may succeed and point to value = 2.
Expected behavior
After step 3, the FetchProcess.execute() should fail with a LOCK_FAILURE and the refs/heads/localfoo should have the value=3, which is the update at step 2 that won the race.
The modification happens during the execution of the command and shouldn't silently overwrite the destination ref depending on the concurrency and timing of the local operation.
Relevant log output
Other information
I believe the problem is in the sequence of the logical locking of the refs/heads/localfoo.
The fetch of the refs/heads/localfoo happens in the want(Ref src, RefSpec spec) function, when the remote ref and its value have already been fetched; however, things may have changed because nothing was locked before then.
If the local ref-update occurs after the execution of want(Ref src, RefSpec spec), it is detected, but any prior modification would go unnoticed and therefore could be lost or overwritten.