lock: block signal interrupt while making a lock file
On Windows where symlink isn't supported, util.makelock() could leave an empty
file if interrupted immediately after os.open(). This empty lock never dies
as it has no process id recorded.
ld = os.open(pathname, os.O_CREAT | os.O_WRONLY | os.O_EXCL)
# an interrupt may occur here
os.write(ld, info)
os.close(ld)
This was a long-standing bug of TortoiseHg which runs a command-server and
kills it by CTRL_C_EVENT, reported by random Windows users.
https://bitbucket.org/tortoisehg/thg/issues/4873/#comment-
43591129
At first, I tried to fix makelock() to clean up a stale lock file, which
turned out to be hard because any instructions may be interrupted by a
signal.
ld = None
try:
# CALL_FUNCTION # os.open(...)
# an interrupt may occur here
# STORE_FAST # ld = ...
ld = os.open(pathname, os.O_CREAT | os.O_WRONLY | os.O_EXCL)
os.write(ld, info)
...
return True
except:
if ld:
...
os.unlink(pathname)
return False
So I decided to block signals by temporarily replacing the signal handlers
so makelcok() and held = 1 will never be interrupted.
Many thanks to Fernando Najera for investigating the issue.
====================================
Testing head checking code: Case B-3
====================================
Mercurial checks for the introduction of new heads on push. Evolution comes
into play to detect if existing branches on the server are being replaced by
some of the new one we push.
This case is part of a series of tests checking this behavior.
Category B: simple case involving pruned changesets
TestCase 3: multi-changeset branch, other is pruned, rest is superceeded
.. old-state:
..
.. * 2 changeset branch
..
.. new-state:
..
.. * old head is superceeded
.. * old other is pruned
..
.. expected-result:
..
.. * push allowed
..
.. graph-summary:
..
.. B ø⇠◔ B'
.. | |
.. A ⊗ |
.. |/
.. ●
$ . $TESTDIR/testlib/push-checkheads-util.sh
Test setup
----------
$ mkdir B3
$ cd B3
$ setuprepos
creating basic server and client repo
updating to branch default
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cd server
$ mkcommit B0
$ cd ../client
$ hg pull
pulling from $TESTTMP/B3/server
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
new changesets d73caddc5533
(run 'hg update' to get a working copy)
$ hg up 0
0 files updated, 0 files merged, 1 files removed, 0 files unresolved
$ mkcommit B1
created new head
$ hg debugobsolete --record-parents `getid "desc(A0)"`
obsoleted 1 changesets
1 new orphan changesets
$ hg debugobsolete `getid "desc(B0)" ` `getid "desc(B1)"`
obsoleted 1 changesets
$ hg log -G --hidden
@ 25c56d33e4c4 (draft): B1
|
| x d73caddc5533 (draft): B0
| |
| x 8aaa48160adc (draft): A0
|/
o 1e4be0697311 (public): root
Actual testing
--------------
$ hg push
pushing to $TESTTMP/B3/server
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files (+1 heads)
2 new obsolescence markers
obsoleted 2 changesets
$ cd ../..