threads / discuss / 62844

unlink errors under windows in git pack-refs

Subject: unlink errors under windows in git pack-refs

## tl;dr

2 messages between Jan 22, 2025 and Jan 24, 2025.

replies: 1people: 2as markdown or json

Christian Reich· Jan 22, 2025, 19:01 UTC · lore
What did you do before the bug happened? (Steps to reproduce your issue)
I have a git repository cloned which uses reftables.
git clone --ref-format=reftable https://github.com/eclipse-jgit/jgit.git

A jgit-program (java) is running and sleeping for 100seconds to demonstrate the problem.

         Git git = Git.init().setDirectory(new 
File("c:\\temp\\jgit")).call();
         FileRepository repo = (FileRepository) git.getRepository();
         try {
             Thread.sleep(100000);
         } catch (InterruptedException e) {
         }
         git.close();

While the jgit-program is sleeping in git-bash update a ref und pack the reftablefiles:

git update-ref refs/tags/test 939d321faccd12bff4cb13ce6358820297fbc78e
git pack-refs
What did you expect to happen? (Expected behavior)
git pack-refs should work without messages.
What happened instead? (Actual behavior)

git tries to unlink the reftable-files, but jgit hold windows-system lock, so the file can't be unlinked. An answers 'n' for retry causes more asks. After the third try git give up.

Unlink of file 'C:/temp/jgittest/jgit/.git/reftable/0x000000000002-0x000000000004-50486d0e.ref' failed. Should I try again? (y/n) n Unlink of file 'C:/temp/jgittest/jgit/.git/reftable/0x000000000002-0x000000000004-50486d0e.ref' failed. Should I try again? (y/n) n Unlink of file 'C:/temp/jgittest/jgit/.git/reftable/0x000000000002-0x000000000004-50486d0e.ref' failed. Should I try again? (y/n) n

What's different between what you expected and what actually happened?

I would expect, that git tries to unlink the files. But if this fails git should ignore this and try to delete the files next time on pack-files. Its documented in https://git-scm.com/docs/reftable

Anything else you want to add:

Please review the rest of the bug report below. You can delete any lines you don't wish to share.

[System Info]
git version:
git version 2.48.0.rc2.windows.1
cpu: x86_64
built from commit: 049f0cf1a5d000f1e24f0e80b79b0d043a8b83b2
sizeof-long: 4
sizeof-size_t: 8
shell-path: D:/git-sdk-64-build-installers/usr/bin/sh
feature: fsmonitor--daemon
libcurl: 8.11.1
OpenSSL: OpenSSL 3.2.3 3 Sep 2024
zlib: 1.3.1
uname: Windows 10.0 22631
compiler info: gnuc: 14.2
libc info: no libc information available
$SHELL (typically, interactive shell): C:\Program Files\Git\usr\bin\bash.exe

[Enabled Hooks] commit-msg

Patrick Steinhardt· Jan 24, 2025, 06:36 UTC · re: Christian Reich · lore

Re: unlink errors under windows in git pack-refs

On Wed, Jan 22, 2025 at 08:01:31PM +0100, Christian Reich wrote:
Show 19 quoted lines
> What happened instead? (Actual behavior)
> 
> git tries to unlink the reftable-files, but jgit hold windows-system lock,
> so the file can't be unlinked.
> An answers 'n' for retry causes more asks. After the third try git give up.
> 
> Unlink of file 'C:/temp/jgittest/jgit/.git/reftable/0x000000000002-0x000000000004-50486d0e.ref'
> failed. Should I try again? (y/n) n
> Unlink of file 'C:/temp/jgittest/jgit/.git/reftable/0x000000000002-0x000000000004-50486d0e.ref'
> failed. Should I try again? (y/n) n
> Unlink of file 'C:/temp/jgittest/jgit/.git/reftable/0x000000000002-0x000000000004-50486d0e.ref'
> failed. Should I try again? (y/n) n
> 
> 
> What's different between what you expected and what actually happened?
> 
> I would expect, that git tries to unlink the files. But if this fails git
> should ignore this and try to delete the files next time on pack-files. Its
> documented in https://git-scm.com/docs/reftable

Yeah, very true, it is expected that unlinking old reftables may fail, and this should be totally benign indeed. In fact, none of the callsites of unlink(3p) even check its return value and we just continue to run witih stale files.

The question comes from `mingw_unlink()`, which we use on Windows platforms:

	while (ret == -1 && is_file_in_use_error(GetLastError()) &&
	       ask_yes_no_if_possible("Unlink of file '%s' failed. "
			"Should I try again?", pathname))
	       ret = _wunlink(wpathname);

As you can see, the loop should immediately exit when you answer 'n', and I assume that this even happens. So where do the other asks come from? One such location is in `reftable_be_pack_refs()`, which calls `reftable_stack_clean()`. This function will try to prune any old tables which aren't referenced anymore. The other callsite comes from reloading the stack, where we again try to unlink now-unreferenced tables. All of these calls are benign.

So the problem is that we use the EBUSY-handling in `mingw_unlink()` in the first place. I'll send a patch in a bit to address this issue.

Thanks for the report!
Patrick

← back to recent threads