git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* v2.46.0-rc0 test failures on cygwin
@ 2024-07-16 19:45 Ramsay Jones
  2024-07-17  6:42 ` Jeff King
  2024-07-23 12:31 ` [PATCH] refs: fix format migration on Cygwin Patrick Steinhardt
  0 siblings, 2 replies; 15+ messages in thread
From: Ramsay Jones @ 2024-07-16 19:45 UTC (permalink / raw)
  To: GIT Mailing-list; +Cc: Patrick Steinhardt, Adam Dinwoodie, Junio C Hamano


The 'Test Summary Report' for the v2.46.0-rc0 test run, on cygwin, includes:

  ...
  t1460-refs-migrate.sh                            (Wstat: 256 (exited 1) Tests: 30 Failed: 9)
    Failed tests:  8-15, 29
    Non-zero exit status: 1
  ...

Looking at the test output directly, we see:
 
  $ pwd
  /home/ramsay/git
  $ cd t
  $ make clean
  rm -f -r 'chainlinttmp'
  rm -f -r 'trash directory'.*
  rm -f -r valgrind/bin
  rm -f -r 'test-results'
  rm -f .prove
  $ ./t1460-refs-migrate.sh -v -i
  ...
  ok 7 - files -> reftable: migration with worktree fails
  
  expecting success of 1460.8 'files -> reftable: unborn HEAD': 
  			test_when_finished "rm -rf repo" &&
  			git init --ref-format=$from_format repo &&
  			test_migration repo "$to_format"
  		
  Initialized empty Git repository in /home/ramsay/git/t/trash directory.t1460-refs-migrate/repo/.git/
  error: could not link file '.git/ref_migration.sr9pEF/reftable' to '.git/reftable': Permission denied
  migrated refs can be found at '.git/ref_migration.sr9pEF'
  not ok 8 - files -> reftable: unborn HEAD
  #	
  #				test_when_finished "rm -rf repo" &&
  #				git init --ref-format=$from_format repo &&
  #				test_migration repo "$to_format"
  #			
  1..8
  $ 

Note that all of the errors in this test look similar to this one (ie. when
rename()-ing the 'migrated' reftable directory to .git/reftable we get an
'Permission denied' error). So the error message is from line 2672 of refs.c
in the move_files() function.

Let's have a quick look at the test directory:

  $ cd trash\ directory.t1460-refs-migrate/
  $ ls
  err  expect  repo/
  $ cd repo
  $ ls -l .git
  total 7.0K
  drwxr-xr-x 1 ramsay None  0 Jul 16 19:53 branches/
  -rw-r--r-- 1 ramsay None 86 Jul 16 19:53 config
  -rw-r--r-- 1 ramsay None 73 Jul 16 19:53 description
  -rw-r--r-- 1 ramsay None 25 Jul 16 19:53 HEAD
  drwxr-xr-x 1 ramsay None  0 Jul 16 19:53 hooks/
  drwxr-xr-x 1 ramsay None  0 Jul 16 19:53 info/
  drwxr-xr-x 1 ramsay None  0 Jul 16 19:53 objects/
  drwx------ 1 ramsay None  0 Jul 16 19:53 ref_migration.sr9pEF/
  drwxr-xr-x 1 ramsay None  0 Jul 16 19:53 refs/

Now try to finish the migration by hand:

  $ mv .git/ref_migration.sr9pEF/reftable .git/reftable

Hmm, note no error; of course, the mv command may well do much more than
the rename() library function, so they are not necessarily equivalent.

  $ ls -l .git
  total 7.0K
  drwxr-xr-x 1 ramsay None  0 Jul 16 19:53 branches/
  -rw-r--r-- 1 ramsay None 86 Jul 16 19:53 config
  -rw-r--r-- 1 ramsay None 73 Jul 16 19:53 description
  -rw-r--r-- 1 ramsay None 25 Jul 16 19:53 HEAD
  drwxr-xr-x 1 ramsay None  0 Jul 16 19:53 hooks/
  drwxr-xr-x 1 ramsay None  0 Jul 16 19:53 info/
  drwxr-xr-x 1 ramsay None  0 Jul 16 19:53 objects/
  drwx------ 1 ramsay None  0 Jul 16 19:55 ref_migration.sr9pEF/
  drwxr-xr-x 1 ramsay None  0 Jul 16 19:53 refs/
  drwxr-xr-x 1 ramsay None  0 Jul 16 19:53 reftable/
  $ 
  $ rm -rf .git/ref_migration.sr9pEF/
  $ git branch -v
  fatal: failed to resolve HEAD as a valid ref
  $ ls -l .git/reftable
  total 2.0K
  -rw-r--r-- 1 ramsay None 124 Jul 16 19:53 0x000000000001-0x000000000001-64e987ec.ref
  -rw-r--r-- 1 ramsay None  43 Jul 16 19:53 tables.list
  $ xxd .git/reftable/0x000000000001-0x000000000001-64e987ec.ref 
  00000000: 5245 4654 0100 1000 0000 0000 0000 0001  REFT............
  00000010: 0000 0000 0000 0001 7200 0038 0023 4845  ........r..8.#HE
  00000020: 4144 000f 7265 6673 2f68 6561 6473 2f6d  AD..refs/heads/m
  00000030: 6169 6e00 001c 0001 5245 4654 0100 1000  ain.....REFT....
  00000040: 0000 0000 0000 0001 0000 0000 0000 0001  ................
  00000050: 0000 0000 0000 0000 0000 0000 0000 0000  ................
  00000060: 0000 0000 0000 0000 0000 0000 0000 0000  ................
  00000070: 0000 0000 0000 0000 b6bf f78a            ............
  $ 

So, the HEAD ref was referring to refs/heads/main.

  $ pwd
  /home/ramsay/git/t/trash directory.t1460-refs-migrate/repo
  $ git init --ref-format=reftable
  fatal: attempt to reinitialize repository with different reference storage format
  $ xxd .git/refs/heads 
  00000000: 7468 6973 2072 6570 6f73 6974 6f72 7920  this repository 
  00000010: 7573 6573 2074 6865 2072 6566 7461 626c  uses the reftabl
  00000020: 6520 666f 726d 6174 0a                   e format.
  $ 
  $ git branch -v
  fatal: failed to resolve HEAD as a valid ref
  $ 
 
Hmm, so quite broken :)

Maybe the order of some of the actions in repo_migrate_ref_storage_format() may
need to be re-thought! ;)

The 'man 3 rename' is not very enlightening; 'The conditions for failure depend
on the host operating system.'

Unfortunately, I don't have any (well much) spare time to dig further into
this at the moment, so I thought I should at least report it here for others
to hopefully find a solution.

ATB,
Ramsay Jones


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: v2.46.0-rc0 test failures on cygwin
  2024-07-16 19:45 v2.46.0-rc0 test failures on cygwin Ramsay Jones
@ 2024-07-17  6:42 ` Jeff King
  2024-07-17 14:48   ` Junio C Hamano
  2024-07-17 18:05   ` Ramsay Jones
  2024-07-23 12:31 ` [PATCH] refs: fix format migration on Cygwin Patrick Steinhardt
  1 sibling, 2 replies; 15+ messages in thread
From: Jeff King @ 2024-07-17  6:42 UTC (permalink / raw)
  To: Ramsay Jones
  Cc: GIT Mailing-list, Patrick Steinhardt, Adam Dinwoodie,
	Junio C Hamano

On Tue, Jul 16, 2024 at 08:45:48PM +0100, Ramsay Jones wrote:

>   error: could not link file '.git/ref_migration.sr9pEF/reftable' to '.git/reftable': Permission denied
>   migrated refs can be found at '.git/ref_migration.sr9pEF'
> [...]
> Now try to finish the migration by hand:
> 
>   $ mv .git/ref_migration.sr9pEF/reftable .git/reftable
> 
> Hmm, note no error; of course, the mv command may well do much more than
> the rename() library function, so they are not necessarily equivalent.

This is a shot in the dark, but: could the problem be an open file that
cannot be moved? If I run a "ref migrate" on my Linux system in the
debugger and stop at move_files(), checking /proc/<pid>/fd shows an open
descriptor for .git/ref_migration.WnJ8TS/reftable/tables.list.

Does the patch below fix things for you? I'm not too familiar with the
code, so this is what I cobbled together.  The best response will be
from Patrick, but I think he's offline for another week or so. In the
meantime, this at least doesn't crash for me. ;) And I confirmed that
the tables.list file is closed during the move_files() call.

-Peff

---
diff --git a/refs.c b/refs.c
index bb90a18875..06a0fc5099 100644
--- a/refs.c
+++ b/refs.c
@@ -2843,6 +2843,12 @@ int repo_migrate_ref_storage_format(struct repository *repo,
 		goto done;
 	}
 
+	/*
+	 * Close the new ref store to avoid holding on to any open files
+	 * which could interfere with moving things behind the scenes.
+	 */
+	ref_store_release(new_refs);
+
 	/*
 	 * Until now we were in the non-destructive phase, where we only
 	 * populated the new ref store. From hereon though we are about
@@ -2874,8 +2880,13 @@ int repo_migrate_ref_storage_format(struct repository *repo,
 	 */
 	initialize_repository_version(hash_algo_by_ptr(repo->hash_algo), format, 1);
 
-	free(new_refs->gitdir);
-	new_refs->gitdir = xstrdup(old_refs->gitdir);
+	/*
+	 * Re-open the now-migrated ref store. I'm not sure if this is strictly
+	 * needed or not. Perhaps it would also be a good time to check that
+	 * we correctly opened it, it's in the expected format, etc?
+	 */
+	new_refs = ref_store_init(repo, format, old_refs->gitdir,
+				  REF_STORE_ALL_CAPS);
 	repo->refs_private = new_refs;
 	ref_store_release(old_refs);
 

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: v2.46.0-rc0 test failures on cygwin
  2024-07-17  6:42 ` Jeff King
@ 2024-07-17 14:48   ` Junio C Hamano
  2024-07-17 18:10     ` Ramsay Jones
  2024-07-17 18:05   ` Ramsay Jones
  1 sibling, 1 reply; 15+ messages in thread
From: Junio C Hamano @ 2024-07-17 14:48 UTC (permalink / raw)
  To: Jeff King
  Cc: Ramsay Jones, GIT Mailing-list, Patrick Steinhardt,
	Adam Dinwoodie

Jeff King <peff@peff.net> writes:

> On Tue, Jul 16, 2024 at 08:45:48PM +0100, Ramsay Jones wrote:
>
>>   error: could not link file '.git/ref_migration.sr9pEF/reftable' to '.git/reftable': Permission denied
>>   migrated refs can be found at '.git/ref_migration.sr9pEF'
>> [...]
>> Now try to finish the migration by hand:
>> 
>>   $ mv .git/ref_migration.sr9pEF/reftable .git/reftable
>> 
>> Hmm, note no error; of course, the mv command may well do much more than
>> the rename() library function, so they are not necessarily equivalent.
>
> This is a shot in the dark, but: could the problem be an open file that
> cannot be moved? If I run a "ref migrate" on my Linux system in the
> debugger and stop at move_files(), checking /proc/<pid>/fd shows an open
> descriptor for .git/ref_migration.WnJ8TS/reftable/tables.list.

Hmph, I wonder ifthat means the same test should be failing on
Windows, too?

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: v2.46.0-rc0 test failures on cygwin
  2024-07-17  6:42 ` Jeff King
  2024-07-17 14:48   ` Junio C Hamano
@ 2024-07-17 18:05   ` Ramsay Jones
  2024-07-18  0:57     ` Jeff King
  1 sibling, 1 reply; 15+ messages in thread
From: Ramsay Jones @ 2024-07-17 18:05 UTC (permalink / raw)
  To: Jeff King
  Cc: GIT Mailing-list, Patrick Steinhardt, Adam Dinwoodie,
	Junio C Hamano



On 17/07/2024 07:42, Jeff King wrote:
> On Tue, Jul 16, 2024 at 08:45:48PM +0100, Ramsay Jones wrote:
> 
>>   error: could not link file '.git/ref_migration.sr9pEF/reftable' to '.git/reftable': Permission denied
>>   migrated refs can be found at '.git/ref_migration.sr9pEF'
>> [...]
>> Now try to finish the migration by hand:
>>
>>   $ mv .git/ref_migration.sr9pEF/reftable .git/reftable
>>
>> Hmm, note no error; of course, the mv command may well do much more than
>> the rename() library function, so they are not necessarily equivalent.
> 
> This is a shot in the dark, but: could the problem be an open file that
> cannot be moved? If I run a "ref migrate" on my Linux system in the
> debugger and stop at move_files(), checking /proc/<pid>/fd shows an open
> descriptor for .git/ref_migration.WnJ8TS/reftable/tables.list.

Heh, a very good shot in the dark! ;)

> Does the patch below fix things for you? I'm not too familiar with the
> code, so this is what I cobbled together.  The best response will be
> from Patrick, but I think he's offline for another week or so. In the
> meantime, this at least doesn't crash for me. ;) And I confirmed that
> the tables.list file is closed during the move_files() call.

The patch given below fixes the test for me! (I have only run t1460-refs-migrate.sh,
since the full test-suite takes 6 hours to run, but now all 30 tests pass!)

I also don't know the code well enough to answer your question regarding
the re-opening of the migrated ref-store, but it doesn't look like it would
cause any problems (famous last words).

Thanks!

ATB,
Ramsay Jones

> ---
> diff --git a/refs.c b/refs.c
> index bb90a18875..06a0fc5099 100644
> --- a/refs.c
> +++ b/refs.c
> @@ -2843,6 +2843,12 @@ int repo_migrate_ref_storage_format(struct repository *repo,
>  		goto done;
>  	}
>  
> +	/*
> +	 * Close the new ref store to avoid holding on to any open files
> +	 * which could interfere with moving things behind the scenes.
> +	 */
> +	ref_store_release(new_refs);
> +
>  	/*
>  	 * Until now we were in the non-destructive phase, where we only
>  	 * populated the new ref store. From hereon though we are about
> @@ -2874,8 +2880,13 @@ int repo_migrate_ref_storage_format(struct repository *repo,
>  	 */
>  	initialize_repository_version(hash_algo_by_ptr(repo->hash_algo), format, 1);
>  
> -	free(new_refs->gitdir);
> -	new_refs->gitdir = xstrdup(old_refs->gitdir);
> +	/*
> +	 * Re-open the now-migrated ref store. I'm not sure if this is strictly
> +	 * needed or not. Perhaps it would also be a good time to check that
> +	 * we correctly opened it, it's in the expected format, etc?
> +	 */
> +	new_refs = ref_store_init(repo, format, old_refs->gitdir,
> +				  REF_STORE_ALL_CAPS);
>  	repo->refs_private = new_refs;
>  	ref_store_release(old_refs);
>  
> 

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: v2.46.0-rc0 test failures on cygwin
  2024-07-17 14:48   ` Junio C Hamano
@ 2024-07-17 18:10     ` Ramsay Jones
  0 siblings, 0 replies; 15+ messages in thread
From: Ramsay Jones @ 2024-07-17 18:10 UTC (permalink / raw)
  To: Junio C Hamano, Jeff King
  Cc: GIT Mailing-list, Patrick Steinhardt, Adam Dinwoodie



On 17/07/2024 15:48, Junio C Hamano wrote:
> Jeff King <peff@peff.net> writes:
> 
>> On Tue, Jul 16, 2024 at 08:45:48PM +0100, Ramsay Jones wrote:
>>
>>>   error: could not link file '.git/ref_migration.sr9pEF/reftable' to '.git/reftable': Permission denied
>>>   migrated refs can be found at '.git/ref_migration.sr9pEF'
>>> [...]
>>> Now try to finish the migration by hand:
>>>
>>>   $ mv .git/ref_migration.sr9pEF/reftable .git/reftable
>>>
>>> Hmm, note no error; of course, the mv command may well do much more than
>>> the rename() library function, so they are not necessarily equivalent.
>>
>> This is a shot in the dark, but: could the problem be an open file that
>> cannot be moved? If I run a "ref migrate" on my Linux system in the
>> debugger and stop at move_files(), checking /proc/<pid>/fd shows an open
>> descriptor for .git/ref_migration.WnJ8TS/reftable/tables.list.
> 
> Hmph, I wonder ifthat means the same test should be failing on
> Windows, too?
> 

Since we have not heard anything from Gfw, I had assumed it was cygwin
specific (Gfw uses mingw_rename() not rename() so we should not necessarily
expect it to behave the same).

However, Jeff's patch fixes the problem for me (see other email).

ATB,
Ramsay Jones


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: v2.46.0-rc0 test failures on cygwin
  2024-07-17 18:05   ` Ramsay Jones
@ 2024-07-18  0:57     ` Jeff King
  2024-07-18  1:22       ` Ramsay Jones
  2024-07-23 10:30       ` Patrick Steinhardt
  0 siblings, 2 replies; 15+ messages in thread
From: Jeff King @ 2024-07-18  0:57 UTC (permalink / raw)
  To: Ramsay Jones
  Cc: GIT Mailing-list, Patrick Steinhardt, Adam Dinwoodie,
	Junio C Hamano

On Wed, Jul 17, 2024 at 07:05:43PM +0100, Ramsay Jones wrote:

> > This is a shot in the dark, but: could the problem be an open file that
> > cannot be moved? If I run a "ref migrate" on my Linux system in the
> > debugger and stop at move_files(), checking /proc/<pid>/fd shows an open
> > descriptor for .git/ref_migration.WnJ8TS/reftable/tables.list.
> 
> Heh, a very good shot in the dark! ;)

Lucky guess. :) When Junio pointed out that we'd expect Windows to fail
in that case, too, I thought for sure I was just wrong. So I'm glad it
worked out.

> The patch given below fixes the test for me! (I have only run t1460-refs-migrate.sh,
> since the full test-suite takes 6 hours to run, but now all 30 tests pass!)
> 
> I also don't know the code well enough to answer your question regarding
> the re-opening of the migrated ref-store, but it doesn't look like it would
> cause any problems (famous last words).

Thanks for testing. This is new in the upcoming release, but I think
it's localized to the "git ref migrate" command. So aside from the
annoyance of the test failure for you, it is not too urgent. I'm tempted
to put it off until Patrick has had a chance to weigh in, even if it
means missing the v2.46 cutoff.

I'd also be OK with pursuing it in the meantime if folks feel
differently. Having slept on it, I think the answer to one of my
questions here...

> > -	free(new_refs->gitdir);
> > -	new_refs->gitdir = xstrdup(old_refs->gitdir);
> > +	/*
> > +	 * Re-open the now-migrated ref store. I'm not sure if this is strictly
> > +	 * needed or not. Perhaps it would also be a good time to check that
> > +	 * we correctly opened it, it's in the expected format, etc?
> > +	 */
> > +	new_refs = ref_store_init(repo, format, old_refs->gitdir,
> > +				  REF_STORE_ALL_CAPS);
> >  	repo->refs_private = new_refs;
> >  	ref_store_release(old_refs);

...is that we must put _something_ useful into repo->refs_private,
because old_refs is an alias for it that we are freeing. I suspect that
"git ref migrate" does not really look at the repo any more after this
migration function returns, but it makes sense for it to leave things in
a consistent state.

So my biggest question is just whether there is any downside to doing
the release/init pair rather than trying to reuse the existing struct.

I do think it probably causes a small memory leak. The "init" function
allocates the actual ref_store struct, but the "release" function
doesn't seem to free it. So we are probably leaking the store that
points to the temp directory. But that is also true of "old_refs", or of
"new_refs" if we hit an error. So I think the solution is probably for
init/release to be symmetric, and for the latter to clean up everything.
But again, I'd prefer to get input from Patrick there.

-Peff

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: v2.46.0-rc0 test failures on cygwin
  2024-07-18  0:57     ` Jeff King
@ 2024-07-18  1:22       ` Ramsay Jones
  2024-07-18  4:52         ` Junio C Hamano
  2024-07-21 13:48         ` Adam Dinwoodie
  2024-07-23 10:30       ` Patrick Steinhardt
  1 sibling, 2 replies; 15+ messages in thread
From: Ramsay Jones @ 2024-07-18  1:22 UTC (permalink / raw)
  To: Jeff King
  Cc: GIT Mailing-list, Patrick Steinhardt, Adam Dinwoodie,
	Junio C Hamano



On 18/07/2024 01:57, Jeff King wrote:
> On Wed, Jul 17, 2024 at 07:05:43PM +0100, Ramsay Jones wrote:
[snip]

>> I also don't know the code well enough to answer your question regarding
>> the re-opening of the migrated ref-store, but it doesn't look like it would
>> cause any problems (famous last words).
> 
> Thanks for testing. This is new in the upcoming release, but I think
> it's localized to the "git ref migrate" command. So aside from the
> annoyance of the test failure for you, it is not too urgent. I'm tempted
> to put it off until Patrick has had a chance to weigh in, even if it
> means missing the v2.46 cutoff.

Yes, I think it would be better for Patrick to take a look. I added Adam to
the CC list to keep him in the loop (because he is the cygwin git package
maintainer); he may have a view on the timing issues.

Personally, I would be fine with a post v2.46 fix, but it is not up to me. :)

Thanks.

ATB,
Ramsay Jones


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: v2.46.0-rc0 test failures on cygwin
  2024-07-18  1:22       ` Ramsay Jones
@ 2024-07-18  4:52         ` Junio C Hamano
  2024-07-21 13:48         ` Adam Dinwoodie
  1 sibling, 0 replies; 15+ messages in thread
From: Junio C Hamano @ 2024-07-18  4:52 UTC (permalink / raw)
  To: Ramsay Jones
  Cc: Jeff King, GIT Mailing-list, Patrick Steinhardt, Adam Dinwoodie

Ramsay Jones <ramsay@ramsayjones.plus.com> writes:

> On 18/07/2024 01:57, Jeff King wrote:
>> On Wed, Jul 17, 2024 at 07:05:43PM +0100, Ramsay Jones wrote:
> [snip]
>
>>> I also don't know the code well enough to answer your question regarding
>>> the re-opening of the migrated ref-store, but it doesn't look like it would
>>> cause any problems (famous last words).
>> 
>> Thanks for testing. This is new in the upcoming release, but I think
>> it's localized to the "git ref migrate" command. So aside from the
>> annoyance of the test failure for you, it is not too urgent. I'm tempted
>> to put it off until Patrick has had a chance to weigh in, even if it
>> means missing the v2.46 cutoff.
>
> Yes, I think it would be better for Patrick to take a look. I added Adam to
> the CC list to keep him in the loop (because he is the cygwin git package
> maintainer); he may have a view on the timing issues.
>
> Personally, I would be fine with a post v2.46 fix, but it is not up to me. :)

Thanks.  I am inclined to postpone it after 2.46 final, and not to
disturb Patrick during his honeymoon.


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: v2.46.0-rc0 test failures on cygwin
  2024-07-18  1:22       ` Ramsay Jones
  2024-07-18  4:52         ` Junio C Hamano
@ 2024-07-21 13:48         ` Adam Dinwoodie
  1 sibling, 0 replies; 15+ messages in thread
From: Adam Dinwoodie @ 2024-07-21 13:48 UTC (permalink / raw)
  To: Ramsay Jones
  Cc: Jeff King, GIT Mailing-list, Patrick Steinhardt, Junio C Hamano

On Thu, 18 Jul 2024 at 02:22, Ramsay Jones wrote:
> On 18/07/2024 01:57, Jeff King wrote:
> > On Wed, Jul 17, 2024 at 07:05:43PM +0100, Ramsay Jones wrote:
> [snip]
>
> >> I also don't know the code well enough to answer your question regarding
> >> the re-opening of the migrated ref-store, but it doesn't look like it would
> >> cause any problems (famous last words).
> >
> > Thanks for testing. This is new in the upcoming release, but I think
> > it's localized to the "git ref migrate" command. So aside from the
> > annoyance of the test failure for you, it is not too urgent. I'm tempted
> > to put it off until Patrick has had a chance to weigh in, even if it
> > means missing the v2.46 cutoff.
>
> Yes, I think it would be better for Patrick to take a look. I added Adam to
> the CC list to keep him in the loop (because he is the cygwin git package
> maintainer); he may have a view on the timing issues.
>
> Personally, I would be fine with a post v2.46 fix, but it is not up to me. :)

Absolutely fine with a post-v2.46 fix for Cygwin's official packaging.
Real Life™ has meant I'm not on top of the latest releases anyway, so
needing to wait a bit longer before taking v2.46 won't realistically
make much difference anyway.

Adam

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: v2.46.0-rc0 test failures on cygwin
  2024-07-18  0:57     ` Jeff King
  2024-07-18  1:22       ` Ramsay Jones
@ 2024-07-23 10:30       ` Patrick Steinhardt
  2024-07-23 20:49         ` Jeff King
  1 sibling, 1 reply; 15+ messages in thread
From: Patrick Steinhardt @ 2024-07-23 10:30 UTC (permalink / raw)
  To: Jeff King; +Cc: Ramsay Jones, GIT Mailing-list, Adam Dinwoodie, Junio C Hamano

[-- Attachment #1: Type: text/plain, Size: 5111 bytes --]

On Wed, Jul 17, 2024 at 08:57:23PM -0400, Jeff King wrote:
> On Wed, Jul 17, 2024 at 07:05:43PM +0100, Ramsay Jones wrote:
> > The patch given below fixes the test for me! (I have only run t1460-refs-migrate.sh,
> > since the full test-suite takes 6 hours to run, but now all 30 tests pass!)
> > 
> > I also don't know the code well enough to answer your question regarding
> > the re-opening of the migrated ref-store, but it doesn't look like it would
> > cause any problems (famous last words).
> 
> Thanks for testing. This is new in the upcoming release, but I think
> it's localized to the "git ref migrate" command. So aside from the
> annoyance of the test failure for you, it is not too urgent. I'm tempted
> to put it off until Patrick has had a chance to weigh in, even if it
> means missing the v2.46 cutoff.

Thanks all for digging into this while I was out!

> I'd also be OK with pursuing it in the meantime if folks feel
> differently. Having slept on it, I think the answer to one of my
> questions here...
> 
> > > -	free(new_refs->gitdir);
> > > -	new_refs->gitdir = xstrdup(old_refs->gitdir);
> > > +	/*
> > > +	 * Re-open the now-migrated ref store. I'm not sure if this is strictly
> > > +	 * needed or not. Perhaps it would also be a good time to check that
> > > +	 * we correctly opened it, it's in the expected format, etc?
> > > +	 */
> > > +	new_refs = ref_store_init(repo, format, old_refs->gitdir,
> > > +				  REF_STORE_ALL_CAPS);
> > >  	repo->refs_private = new_refs;
> > >  	ref_store_release(old_refs);
> 
> ...is that we must put _something_ useful into repo->refs_private,
> because old_refs is an alias for it that we are freeing. I suspect that
> "git ref migrate" does not really look at the repo any more after this
> migration function returns, but it makes sense for it to leave things in
> a consistent state.

Yeah, `repo->refs_private` shouldn't ever be accessed after the
migration has finished. Still, as you say, it feels like the correct
thing to do to keep the `repo` in a consistent state, even though it's
not necessary in our codebase right now.

> So my biggest question is just whether there is any downside to doing
> the release/init pair rather than trying to reuse the existing struct.

There shouldn't be any downside, but it is wasted effort. The main ref
store should always be accessed via `get_main_ref_store()`, and that
function knows to lazily initialize the refdb as required. So instead, I
think the preferable fix is to release the new ref store after we have
populated it and set the main ref store of the repository to `NULL`
instead of re-initializing it.

So the following should be sufficient:

    diff --git a/refs.c b/refs.c
    index bb90a18875..915aeb4d1d 100644
    --- a/refs.c
    +++ b/refs.c
    @@ -2843,6 +2843,14 @@ int repo_migrate_ref_storage_format(struct repository *repo,
            goto done;
        }
     
    +	/*
    +	 * Release the new ref store such that any potentially-open files will
    +	 * be closed. This is required for platforms like Cygwin, where
    +	 * renaming an open file results in EPERM.
    +	 */
    +	ref_store_release(new_refs);
    +	FREE_AND_NULL(new_refs);
    +
        /*
         * Until now we were in the non-destructive phase, where we only
         * populated the new ref store. From hereon though we are about
    @@ -2874,10 +2882,14 @@ int repo_migrate_ref_storage_format(struct repository *repo,
         */
        initialize_repository_version(hash_algo_by_ptr(repo->hash_algo), format, 1);
     
    -	free(new_refs->gitdir);
    -	new_refs->gitdir = xstrdup(old_refs->gitdir);
    -	repo->refs_private = new_refs;
    +	/*
    +	 * Unset the old ref store and release it. `get_main_ref_store()` will
    +	 * make sure to lazily re-initialize the repository's ref store with
    +	 * the new format.
    +	 */
        ref_store_release(old_refs);
    +	FREE_AND_NULL(old_refs);
    +	repo->refs_private = NULL;
     
        ret = 0;
     
    @@ -2888,8 +2900,10 @@ int repo_migrate_ref_storage_format(struct repository *repo,
                    new_gitdir.buf);
        }
     
    -	if (ret && new_refs)
    +	if (new_refs) {
            ref_store_release(new_refs);
    +		free(new_refs);
    +	}
        ref_transaction_free(transaction);
        strbuf_release(&new_gitdir);
        return ret;

> I do think it probably causes a small memory leak. The "init" function
> allocates the actual ref_store struct, but the "release" function
> doesn't seem to free it. So we are probably leaking the store that
> points to the temp directory. But that is also true of "old_refs", or of
> "new_refs" if we hit an error. So I think the solution is probably for
> init/release to be symmetric, and for the latter to clean up everything.
> But again, I'd prefer to get input from Patrick there.

Yeah, we'd have to free the new ref store struct, as well. I wouldn't
make `release()` free the structure as that would be uncustomarily
named.

Patrick

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH] refs: fix format migration on Cygwin
  2024-07-16 19:45 v2.46.0-rc0 test failures on cygwin Ramsay Jones
  2024-07-17  6:42 ` Jeff King
@ 2024-07-23 12:31 ` Patrick Steinhardt
  2024-07-23 19:29   ` Ramsay Jones
  2024-07-23 20:52   ` Jeff King
  1 sibling, 2 replies; 15+ messages in thread
From: Patrick Steinhardt @ 2024-07-23 12:31 UTC (permalink / raw)
  To: git; +Cc: Ramsay Jones, Jeff King, Junio C Hamano, Adam Dinwoodie

[-- Attachment #1: Type: text/plain, Size: 3021 bytes --]

It was reported that t1460-refs-migrate.sh fails when using Cygwin with
errors like the following:

    error: could not link file '.git/ref_migration.sr9pEF/reftable' to '.git/reftable': Permission denied

As some debugging surfaced, the root cause of this is that some files of
the newly-initialized ref store are still open when the target format is
the "reftable" format, and Cygwin refuses to rename open files.

Fix this issue by closing the new ref store before renaming its files
into place. This is a slight change in behaviour compared to before,
where we kept the new ref store open and then updated the repository's
ref store to point to it.

While we could re-open the new ref store after we have moved files
around, this is ultimately unnecessary. We know that the only user of
`repo_migrate_ref_storage_format()` is the git-refs(1) command, and it
won't access the ref store after it has been migrated anyway. So
reinitializing the ref store would be a waste of time. Regardless of
that it is still sensible to leave the repository in a consistent state.
But instead of reinitializing the ref store, we can simply unset the
repo's ref store altogether and let `get_main_ref_store()` lazily
initialize the new ref store as required.

Reported-by: Ramsay Jones <ramsay@ramsayjones.plus.com>
Helped-by: Jeff King <peff@peff.net>
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 refs.c | 22 ++++++++++++++++++----
 1 file changed, 18 insertions(+), 4 deletions(-)

diff --git a/refs.c b/refs.c
index bb90a18875..915aeb4d1d 100644
--- a/refs.c
+++ b/refs.c
@@ -2843,6 +2843,14 @@ int repo_migrate_ref_storage_format(struct repository *repo,
 		goto done;
 	}
 
+	/*
+	 * Release the new ref store such that any potentially-open files will
+	 * be closed. This is required for platforms like Cygwin, where
+	 * renaming an open file results in EPERM.
+	 */
+	ref_store_release(new_refs);
+	FREE_AND_NULL(new_refs);
+
 	/*
 	 * Until now we were in the non-destructive phase, where we only
 	 * populated the new ref store. From hereon though we are about
@@ -2874,10 +2882,14 @@ int repo_migrate_ref_storage_format(struct repository *repo,
 	 */
 	initialize_repository_version(hash_algo_by_ptr(repo->hash_algo), format, 1);
 
-	free(new_refs->gitdir);
-	new_refs->gitdir = xstrdup(old_refs->gitdir);
-	repo->refs_private = new_refs;
+	/*
+	 * Unset the old ref store and release it. `get_main_ref_store()` will
+	 * make sure to lazily re-initialize the repository's ref store with
+	 * the new format.
+	 */
 	ref_store_release(old_refs);
+	FREE_AND_NULL(old_refs);
+	repo->refs_private = NULL;
 
 	ret = 0;
 
@@ -2888,8 +2900,10 @@ int repo_migrate_ref_storage_format(struct repository *repo,
 			    new_gitdir.buf);
 	}
 
-	if (ret && new_refs)
+	if (new_refs) {
 		ref_store_release(new_refs);
+		free(new_refs);
+	}
 	ref_transaction_free(transaction);
 	strbuf_release(&new_gitdir);
 	return ret;
-- 
2.46.0.rc1.dirty


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH] refs: fix format migration on Cygwin
  2024-07-23 12:31 ` [PATCH] refs: fix format migration on Cygwin Patrick Steinhardt
@ 2024-07-23 19:29   ` Ramsay Jones
  2024-07-23 20:13     ` Junio C Hamano
  2024-07-23 20:52   ` Jeff King
  1 sibling, 1 reply; 15+ messages in thread
From: Ramsay Jones @ 2024-07-23 19:29 UTC (permalink / raw)
  To: Patrick Steinhardt, git; +Cc: Jeff King, Junio C Hamano, Adam Dinwoodie



On 23/07/2024 13:31, Patrick Steinhardt wrote:
> It was reported that t1460-refs-migrate.sh fails when using Cygwin with
> errors like the following:
> 
>     error: could not link file '.git/ref_migration.sr9pEF/reftable' to '.git/reftable': Permission denied
> 
> As some debugging surfaced, the root cause of this is that some files of
> the newly-initialized ref store are still open when the target format is
> the "reftable" format, and Cygwin refuses to rename open files.
> 
> Fix this issue by closing the new ref store before renaming its files
> into place. This is a slight change in behaviour compared to before,
> where we kept the new ref store open and then updated the repository's
> ref store to point to it.
> 
> While we could re-open the new ref store after we have moved files
> around, this is ultimately unnecessary. We know that the only user of
> `repo_migrate_ref_storage_format()` is the git-refs(1) command, and it
> won't access the ref store after it has been migrated anyway. So
> reinitializing the ref store would be a waste of time. Regardless of
> that it is still sensible to leave the repository in a consistent state.
> But instead of reinitializing the ref store, we can simply unset the
> repo's ref store altogether and let `get_main_ref_store()` lazily
> initialize the new ref store as required.
> 
> Reported-by: Ramsay Jones <ramsay@ramsayjones.plus.com>
> Helped-by: Jeff King <peff@peff.net>
> Signed-off-by: Patrick Steinhardt <ps@pks.im>
> ---

I applied this patch on top of v2.46.0-rc1, on both Linux and cygwin, and
ran the tests (just t1460-*.sh on cygwin, complete test-suite in Linux).

I can confirm all 30 tests pass on cygwin! :)

Thanks all.

ATB,
Ramsay Jones


>  refs.c | 22 ++++++++++++++++++----
>  1 file changed, 18 insertions(+), 4 deletions(-)
> 
> diff --git a/refs.c b/refs.c
> index bb90a18875..915aeb4d1d 100644
> --- a/refs.c
> +++ b/refs.c
> @@ -2843,6 +2843,14 @@ int repo_migrate_ref_storage_format(struct repository *repo,
>  		goto done;
>  	}
>  
> +	/*
> +	 * Release the new ref store such that any potentially-open files will
> +	 * be closed. This is required for platforms like Cygwin, where
> +	 * renaming an open file results in EPERM.
> +	 */
> +	ref_store_release(new_refs);
> +	FREE_AND_NULL(new_refs);
> +
>  	/*
>  	 * Until now we were in the non-destructive phase, where we only
>  	 * populated the new ref store. From hereon though we are about
> @@ -2874,10 +2882,14 @@ int repo_migrate_ref_storage_format(struct repository *repo,
>  	 */
>  	initialize_repository_version(hash_algo_by_ptr(repo->hash_algo), format, 1);
>  
> -	free(new_refs->gitdir);
> -	new_refs->gitdir = xstrdup(old_refs->gitdir);
> -	repo->refs_private = new_refs;
> +	/*
> +	 * Unset the old ref store and release it. `get_main_ref_store()` will
> +	 * make sure to lazily re-initialize the repository's ref store with
> +	 * the new format.
> +	 */
>  	ref_store_release(old_refs);
> +	FREE_AND_NULL(old_refs);
> +	repo->refs_private = NULL;
>  
>  	ret = 0;
>  
> @@ -2888,8 +2900,10 @@ int repo_migrate_ref_storage_format(struct repository *repo,
>  			    new_gitdir.buf);
>  	}
>  
> -	if (ret && new_refs)
> +	if (new_refs) {
>  		ref_store_release(new_refs);
> +		free(new_refs);
> +	}
>  	ref_transaction_free(transaction);
>  	strbuf_release(&new_gitdir);
>  	return ret;

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] refs: fix format migration on Cygwin
  2024-07-23 19:29   ` Ramsay Jones
@ 2024-07-23 20:13     ` Junio C Hamano
  0 siblings, 0 replies; 15+ messages in thread
From: Junio C Hamano @ 2024-07-23 20:13 UTC (permalink / raw)
  To: Ramsay Jones; +Cc: Patrick Steinhardt, git, Jeff King, Adam Dinwoodie

Ramsay Jones <ramsay@ramsayjones.plus.com> writes:

>> Reported-by: Ramsay Jones <ramsay@ramsayjones.plus.com>
>> Helped-by: Jeff King <peff@peff.net>
>> Signed-off-by: Patrick Steinhardt <ps@pks.im>
>> ---
>
> I applied this patch on top of v2.46.0-rc1, on both Linux and cygwin, and
> ran the tests (just t1460-*.sh on cygwin, complete test-suite in Linux).
>
> I can confirm all 30 tests pass on cygwin! :)

Let's merge it down through 'next' to 'master' and have it in the
upcoming release.

Thanks, all.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: v2.46.0-rc0 test failures on cygwin
  2024-07-23 10:30       ` Patrick Steinhardt
@ 2024-07-23 20:49         ` Jeff King
  0 siblings, 0 replies; 15+ messages in thread
From: Jeff King @ 2024-07-23 20:49 UTC (permalink / raw)
  To: Patrick Steinhardt
  Cc: Ramsay Jones, GIT Mailing-list, Adam Dinwoodie, Junio C Hamano

On Tue, Jul 23, 2024 at 12:30:27PM +0200, Patrick Steinhardt wrote:

> > So my biggest question is just whether there is any downside to doing
> > the release/init pair rather than trying to reuse the existing struct.
> 
> There shouldn't be any downside, but it is wasted effort. The main ref
> store should always be accessed via `get_main_ref_store()`, and that
> function knows to lazily initialize the refdb as required. So instead, I
> think the preferable fix is to release the new ref store after we have
> populated it and set the main ref store of the repository to `NULL`
> instead of re-initializing it.

Ah, that is even better. I'm not too worried about wasted effort (this
is a one-time thing during the ref backend migration), but I think we
are better off leaving as much to the "regular" ref code as possible.

> So the following should be sufficient:
> [...]

Yeah, that looks nice.

> > I do think it probably causes a small memory leak. The "init" function
> > allocates the actual ref_store struct, but the "release" function
> > doesn't seem to free it. So we are probably leaking the store that
> > points to the temp directory. But that is also true of "old_refs", or of
> > "new_refs" if we hit an error. So I think the solution is probably for
> > init/release to be symmetric, and for the latter to clean up everything.
> > But again, I'd prefer to get input from Patrick there.
> 
> Yeah, we'd have to free the new ref store struct, as well. I wouldn't
> make `release()` free the structure as that would be uncustomarily
> named.

We usually don't free in the release() function because it was not
allocated on the init() side in the first place. The real sin here is
that the init/release pair is not symmetric, regardless of what they are
named.

In the patch above you worked around it by just doing a manual free() of
the struct. That's crossing the abstraction barrier a little bit, but I
think is OK in this instance. We don't generally expect a ref stores to
be created and released a lot. If this were a general purpose data
structure like a strbuf that gets used everywhere, I'd be more
concerned.

-Peff

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] refs: fix format migration on Cygwin
  2024-07-23 12:31 ` [PATCH] refs: fix format migration on Cygwin Patrick Steinhardt
  2024-07-23 19:29   ` Ramsay Jones
@ 2024-07-23 20:52   ` Jeff King
  1 sibling, 0 replies; 15+ messages in thread
From: Jeff King @ 2024-07-23 20:52 UTC (permalink / raw)
  To: Patrick Steinhardt; +Cc: git, Ramsay Jones, Junio C Hamano, Adam Dinwoodie

On Tue, Jul 23, 2024 at 02:31:28PM +0200, Patrick Steinhardt wrote:

> @@ -2874,10 +2882,14 @@ int repo_migrate_ref_storage_format(struct repository *repo,
>  	 */
>  	initialize_repository_version(hash_algo_by_ptr(repo->hash_algo), format, 1);
>  
> -	free(new_refs->gitdir);
> -	new_refs->gitdir = xstrdup(old_refs->gitdir);
> -	repo->refs_private = new_refs;
> +	/*
> +	 * Unset the old ref store and release it. `get_main_ref_store()` will
> +	 * make sure to lazily re-initialize the repository's ref store with
> +	 * the new format.
> +	 */
>  	ref_store_release(old_refs);
> +	FREE_AND_NULL(old_refs);
> +	repo->refs_private = NULL;

I think this FREE_AND_NULL() is not technically part of the fix that the
commit message describes. It is fixing an existing leak that happens
when we overwrite repo->refs_private (whether with new_refs or with
NULL).

That said, I don't know that it's worth going back to split it out now.

The rest of the patch looks good to me, and the commit message nicely
describes the problem and solution.

-Peff

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2024-07-23 20:52 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-07-16 19:45 v2.46.0-rc0 test failures on cygwin Ramsay Jones
2024-07-17  6:42 ` Jeff King
2024-07-17 14:48   ` Junio C Hamano
2024-07-17 18:10     ` Ramsay Jones
2024-07-17 18:05   ` Ramsay Jones
2024-07-18  0:57     ` Jeff King
2024-07-18  1:22       ` Ramsay Jones
2024-07-18  4:52         ` Junio C Hamano
2024-07-21 13:48         ` Adam Dinwoodie
2024-07-23 10:30       ` Patrick Steinhardt
2024-07-23 20:49         ` Jeff King
2024-07-23 12:31 ` [PATCH] refs: fix format migration on Cygwin Patrick Steinhardt
2024-07-23 19:29   ` Ramsay Jones
2024-07-23 20:13     ` Junio C Hamano
2024-07-23 20:52   ` Jeff King

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).