Re: concurrent fetches to update same mirror

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Jan 05, 2011 at 03:53:25PM -0500, Jeff King wrote:

> > If both fetch processes try to update the same ref at the same time,
> > one will get the lock and continue, and the other will crash with an
> > error (because the lock was busy).  If one is slightly slower than the
> > other, they will probably update the refs twice, with the slower fetch
> > updating what the faster one had just updated.  :-)
> 
> I assumed it would take the "old" value at the very beginning of the
> fetch (before talking with the remote), and then see that the ref was
> changed under our feet. Or does it simply do it at the end?

Hmm. Weirder even, builtin/fetch.c:s_update_ref takes a "check_old"
flag, and we do always use it for branch updates. But not for tag
updates. I can't think of why. The code blames all the way back to the
original builtin-fetch.

Anyway, when we do check, we check the value from the beginning of the
fetch. So you can get lock conflicts. For example, doing this:

  mkdir repo && cd repo && git init
  echo contents >foo && git add . && git commit -m one
  git update-ref refs/remotes/origin/master refs/heads/master
  git remote add origin some-remote-repo-that-takes-a-few-seconds
  xterm -e 'git fetch -v; read' & xterm -e 'git fetch -v; read'

I.e., putting some cruft into the ref and then updating it. One fetch
will force-write over the ref properly:

   + ac32203...4e64590 master     -> origin/master  (forced update)

but the other one will barf on the lock:

  error: Ref refs/remotes/origin/master is at 4e6459052ab329914c7712a926773e566b8c821d but expected ac32203727daa3bcb5fc041786aa45adbbe86299
  ...
   ! ac32203...4e64590 master     -> origin/master  (unable to update local ref)

Interestingly, in the case of ref _creation_, not update, like this:

  mkdir repo && cd repo && git init
  git remote add origin some-remote-repo-that-takes-a-few-seconds
  xterm -e 'git fetch -v; read' & xterm -e 'git fetch -v; read'

then both will happily update, the second one overwriting the results of
the first. It seems in the case of locking a ref which previously didn't
exist, we don't enforce that it still doesn't exist.

I wonder if we should, but perhaps there is some corner case I am not
considering. The code is in lock_ref_sha1_basic, but blaming didn't turn
up anything helpful.

-Peff
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]