git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: Worktree creation race

From
Duy Nguyen <pclouds@gmail.com>
Date
Feb 1, 2019, 07:06 UTC
Message-ID
<CACsJy8D+zvgtw8RuBefYQsYrvn_vQT1dUO3Veg5ZtfQa2u5QKA@mail.gmail.com>
In-Reply-To
<CAPig+cSdpq0Bfq3zSK8kJd6da3dKixK7qYQ24=ZwbuQtsaLNZw@mail.gmail.com>
Thanks for including me. Apparently I did miss some emails :)
On Fri, Feb 1, 2019 at 1:27 PM Eric Sunshine <sunshine@sunshineco.com> wrote:
Show 31 quoted lines
>
> On Mon, Jan 28, 2019 at 7:58 AM Marketa Calabkova <mcalabkova@suse.cz> wrote:
> > On 15/01/2019 15:03, Marketa Calabkova wrote:
> > > I am writing to report a bug. The original report is from my colleague, I am also providing his suggestions.
> > >
> > > There is insufficient locking for worktree addition. Adding worktree may fail.
> > >
> > > The problem is that git reads the directory entries in $GIT_DIR/worktrees,
> > > finds a worktree name that does not exist, tries to create it, and if an
> > > error is returned adding the worktree fails. When multiple git processes
> > > do this in parallel only one adds a worktree and the others fail. Git should
> > > reread the directory and find a new name that does not exist when creating
> > > the worktree directory fails because another git process already created it.
> > >
> > > I suppose adding PID in the tree name would mitigate the issue to the point it will be very unlikely to encounter.
> > >
> > > I need more than the tree in the temporary directory so using the temporary directory directly as a tree is out of question.
> > >
> > > cd gitrepo
> > > git commit --allow-empty -m Empty
> > > for n in $(seq 10000) ; do ( tmp=$(mktemp -d /dev/shm/gittest/test.XXXXXXXXXXX) ; mkdir $tmp/test ; git worktree add --detach $tmp/test ; ) & done
> > >
> > > (you should see many messages like:
> > > fatal: could not create directory of '.git/worktrees/test284': File exists)
> > >
> > Does anyone has a suggestion what to do with this bug? It looks like a
> > one-line fix probably in builtin/worktree.c, but I have no idea how to
> > do it. Sorry.
>
> I doubt this is a one-line fix, and I don't think it has anything to
> do with reading entries in $GIT_DIR/worktrees.

I never thought people would create worktrees "like crazy" to end up worrying about races like this. The mkdir loop would be one way to go. But I'm going to add a new option to let the user control this directory name. This is necessary since this name is now exposed via "worktrees/<name>" reference space and should also be reported in "git worktree list". Avoiding the race is a nice bonus.

Show 13 quoted lines
> add_worktree() already attempts to give a unique identifier to each
> worktree by adding a numeric suffix and incrementing that suffix if
> the name already exists (such as the 284 in your example error
> message) but there is definitely a race-condition between the time it
> stat()s the name and the time it mkdir()s it.
>
> One possible fix would be to unconditionally use the PID, as you
> suggest, though, this is not necessarily foolproof against races
> either (though it makes collisions very unlikely).
>
> Another possibility would be to skip the stat() and instead do the
> mkdir() in a loop, incrementing the sequence number each time through
> the loop. That should eliminate the race entirely (I think).
-- 
Duy
Previous: Eric SunshineNext: Duy Nguyen
Message 4 of 7 in “Worktree creation race”
  1. Marketa CalabkovaJan 15, 2019
  2. Marketa CalabkovaJan 28, 2019
  3. Eric SunshineFeb 1, 2019
  4. Duy NguyenFeb 1, 2019
  5. Duy NguyenFeb 1, 2019
  6. Eric SunshineFeb 1, 2019
  7. Junio C HamanoFeb 1, 2019

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.