pretxnchangegroup hook fails because it can't acquire lock

Simon King simon at simonking.org.uk
Tue Nov 5 07:06:51 CST 2013


On Tue, Nov 5, 2013 at 12:39 PM, Mick Jordan <mick.jordan at oracle.com> wrote:
> On 11/5/13 3:41 AM, Simon King wrote:
>>
>> On Tue, Nov 5, 2013 at 9:06 AM, Pierre-Yves David
>> <pierre-yves.david at ens-lyon.org> wrote:
>>>
>>> On 5 nov. 2013, at 03:16, Mick Jordan wrote:
>>>
>>>> I have a pretxnchangegroup hook on a repo 'x' that runs a python script
>>>> that, essentially, calls "hg push x-2', where other tests runs to determine
>>>> whether the changegroup should be accepted. The repo is on a server that is
>>>> receiving the push via http, using Apache 2.2 and hgweb. All the repo files
>>>> are group apache and the owner of the files is trusted in the apache user
>>>> .hgrc file. The system is essentially a Red Hat Linux 6.
>>>>
>>>> Mercurial is 2.2.2 and running under Python 2.6.6, which is the default
>>>> installed Python. The hook script is running under python2.7.5, as it needs
>>>> features from that version.
>>>>
>>>> First, 'hg outgoing http://x' works fine, so the basic permissions are
>>>> correct (it too a while to get that far).
>>>>
>>>> However, the 'hg push http://x'  does not. The "hg push x-2" in the hook
>>>> hangs waiting for the lock on 'x' and eventually times out. I can see the
>>>> lock file in 'x/.hg/store' which is a symbolic link to the python process
>>>> running hgweb.cgi (and hence the hook). Now, almost exactly the same
>>>> configuration exists on another machine, running slightly different versions
>>>> of Apache, hg, Linux and python and works flawlessly. So what is the problem
>>>> on my machine? Does 'push' really need the lock? Is it yet another weird
>>>> permissions problem?
>>>>
>>>> I can verify in another shell that I can clone 'x' to, say, 'y', but if
>>>> I also explicitly attempt to then  'hg push 'y' ', I get the same 'waiting
>>>> for lock message'.
>>>>
>>>> Someone who understand the Mercurial locking system please explain why
>>>> this works on one machine but not another?
>>>
>>> from mercurial 2.1, hg push lock the repo (because push may change local
>>> phases). We made that optional (it push anyway if it fails to lock) in 2.6
>>>
>> (For reference, the BTS entry for this was
>> http://bz.selenic.com/show_bug.cgi?id=3684)
>>
>> When the inability to lock the repository is caused by permission
>> problems, the fix in 2.6 is fine. However, in Mick's case, the problem
>> is that the repository is already locked by the parent push process.
>> The child push process tries to lock the repository and eventually
>> times out, and the parent push is rolled back.
>>
>> Steps to reproduce:
>>
>> #------------------------
>> hg init src
>> hg init dest1
>> hg init dest2
>>
>> cat >dest1/.hg/hgrc <<EOF
>> [hooks]
>> pretxnchangegroup.push = hg push ../dest2
>> EOF
>>
>> cat >hgrc <<EOF
>> [ui]
>> timeout=5
>> EOF
>>
>> cd src/
>> touch a
>> hg ci -Am0
>>
>> HGRCPATH=$PWD/../hgrc hg push ../dest1/
>> #------------------------
>>
>> Result:
>>
>> waiting for lock on repository /tmp/simonk/hgtest/dest1 held by 'srv:4187'
>> abort: repository /tmp/simonk/hgtest/dest1: timed out waiting for lock
>> held by srv:4187
>> transaction abort!
>> rollback completed
>> abort: pretxnchangegroup.push hook exited with status 255
>>
>>
>> I worked around this with an in-process hook to perform the push.
>> Because it's in-process, it inherits the parent lock so doesn't have
>> this problem:
>>
>> #------------------------
>> import mercurial.commands
>>
>> # It is no longer possible to run "hg push" in a pretxnchangegroup
>> # hook, because pushing requires locking the repository. This is an
>> # in-python version of the hook that works around the problem.
>> def pushwhilelocked(ui, repo, **kwargs):
>>      destnames = ['ontxnchangegroup', 'default-push', 'default']
>>      for dest in destnames:
>>          path = ui.config('paths', dest, None)
>>          if path is not None:
>>              break
>>      else:
>>          raise mercurial.util.Abort('no path to push to')
>>
>>      return mercurial.commands.push(ui, repo, dest)
>> #------------------------
>>
>> Enable it in the repository with something like:
>>
>> [hooks]
>> pretxnchangegroup.push = python:/path/to/hook/script.py:pushwhilelocked
>>
>>
> I certainly appreciate the explanation and it explains why the other system
> "works" because it is using Mercurial 1.9.1. The problem I see with the
> in-process hook is that it will be running the "wrong" version of Python
> (2.6.6). Is there a way I can install hg to use an alternate version of
> Python. I believe that if I mess with the system version, tools like yum
> will fail, which would be bad.
>

http://mercurial.selenic.com/wiki/UnixInstall describes various
alternative installation options. I think you should be able to do
something like this:

  make install PYTHON=/path/to/python2.7

Simon


More information about the Mercurial mailing list