SV: Corruption issue from filesystem exception.

Sune Foldager cryo at cyanite.org
Fri Feb 6 07:14:10 CST 2009


Hi Matt,

Thanks for the input so far :-)

> > The exception message originates from Windows, I think, and goes  
> > something like "Cannot create a file when that file already exists.".  
> > This is rendered by hg with "abort: " in front, of course. It happens  
> > irregularily during the following situations: commit, pull and,  
> > unfortunately, rebase. The latter corrupts the repository.

> It would of course be very helpful to actually see the command output.
> Do you get a traceback?

I didn't, but I have some more information and a scenario reproducing a
similar problem, see below. First, the error message I got is the same
Windows produces when renaming a file onto an existing one that can't be
replaced (does Mercurial use renaming for atomicity?) E.g. in PowerShell:

C:\src $ mv a b
Move-Item : Cannot create a file when that file already exists.

Same error mercurial returns when in the 'adding file changes' phase of
rebase (presumably strip),

> Do you have copies of any of the damaged repos still?

Yes, I am pretty sure I have. There were two errors and I was able to fix
both with hex editing. I was also able to undo my fixes, of course. The fix
was in both cases decreasing an integer by 1 to make the .i point to the
correct global revision number. I'll dig up the repo.

> It's hard for race conditions to occur in Mercurial. It's
> single-threaded and in normal operation, only one program is ever trying
> to write in .hg at a given time. And there are of course locks to
> prevent multiple writers.

True, I didn't consider that. Thinking more about it, it seems more like a
problem with not being able to back out of being unable to write to files
when stripping.

> Is there anything interesting about your setup? Are you using a network
> filesystem? Do you have virus scanners?

Yes, a virus scanner... that could be the one visiting the file at the wrong
time :-/.


I have a scenario that can produce a similar problem, also leading to
repository corruption. This one involves opening and keeping open an .i
file, preventing mercurial from opening (or at least writing) to it, since
this is the wonderful semantics of keeping files open in windows ;-). It's
pretty simple. There is a dump below:

--------------------------------------------------------------
# The repo has two small files, 'foo' and 'bar', both created in cset 0.
tmp\test $ hg log -g
o  changeset:   3:1c413275cd2c
|  tag:         tip
|  parent:      1:e76ba05487ac
|  user:        Sune Foldager <sune.foldager at edlund.dk>
|  date:        Wed Feb 04 11:23:16 2009 +0100
|  summary:     foo-second
|
| @  changeset:   2:56e617943e89
|/   user:        Sune Foldager <sune.foldager at edlund.dk>
|    date:        Wed Feb 04 11:22:56 2009 +0100
|    summary:     bar-first
|
o  changeset:   1:e76ba05487ac
|  user:        Sune Foldager <sune.foldager at edlund.dk>
|  date:        Wed Feb 04 11:22:45 2009 +0100
|  summary:     first
|
o  changeset:   0:3677ea9ea336
   user:        Sune Foldager <sune.foldager at edlund.dk>
   date:        Wed Feb 04 11:22:32 2009 +0100
   summary:     initial

tmp\test $ hg log --template '{rev}\n' foo
3
1
0
tmp\test $ hg log --template '{rev}\n' bar
2
0
tmp\test $ # at this point, I externally open and keep open foo.i in
.hg/store/data
tmp\test $ hg rebase
saving bundle to C:\tmp\test\.hg\strip-backup\56e617943e89-temp
abort: The process cannot access the file because it is being used by
another process: C:\tmp\test\.hg\store\data/foo.i
tmp\test $ # and now I close it again.
tmp\test $ # oops... the repo is already corrupt now, plus is missing some
csets.
tmp\test $ hg verify
checking changesets
checking manifests
crosschecking files in changesets and manifests
checking files
 foo@?: rev 2 point to nonexistent changeset 3
 (expected 0 1)
 foo@?: 0ecaf80a25cc not in manifests
2 files, 2 changesets, 4 total revisions
1 warnings encountered!
2 integrity errors encountered!
tmp\test $ hg log -g
o  changeset:   1:e76ba05487ac
|  tag:         tip
|  user:        Sune Foldager <sune.foldager at edlund.dk>
|  date:        Wed Feb 04 11:22:45 2009 +0100
|  summary:     first
|
o  changeset:   0:3677ea9ea336
   user:        Sune Foldager <sune.foldager at edlund.dk>
   date:        Wed Feb 04 11:22:32 2009 +0100
   summary:     initial

tmp\test $ # we can unbundle to get those back, leaving the rebase result..
almost.
tmp\test $ hg unbundle .hg/strip-backup/56e617943e89-temp
adding changesets
adding manifests
adding file changes
added 2 changesets with 1 changes to 2 files
(run 'hg update' to get a working copy)
tmp\test $ hg log -g
@  changeset:   3:8e197b4d5490
|  tag:         tip
|  user:        Sune Foldager <sune.foldager at edlund.dk>
|  date:        Wed Feb 04 11:22:56 2009 +0100
|  summary:     bar-first
|
o  changeset:   2:1c413275cd2c
|  user:        Sune Foldager <sune.foldager at edlund.dk>
|  date:        Wed Feb 04 11:23:16 2009 +0100
|  summary:     foo-second
|
o  changeset:   1:e76ba05487ac
|  user:        Sune Foldager <sune.foldager at edlund.dk>
|  date:        Wed Feb 04 11:22:45 2009 +0100
|  summary:     first
|
o  changeset:   0:3677ea9ea336
   user:        Sune Foldager <sune.foldager at edlund.dk>
   date:        Wed Feb 04 11:22:32 2009 +0100
   summary:     initial

tmp\test $ # and still corruption:
tmp\test $ hg verify
checking changesets
checking manifests
crosschecking files in changesets and manifests
checking files
 foo@?: rev 2 point to unexpected changeset 3
 (expected 0 1 2)
2 files, 4 changesets, 5 total revisions
1 warnings encountered!
1 integrity errors encountered!
tmp\test $ # the problem is that foo rev 2 points to cset 3. It should point
to cset 2.
tmp\test $


-- 
Sune Foldager.




More information about the Mercurial-devel mailing list