[PATCH] scmutil: create directories in a race-safe way during update
Thomas Arendsen Hein
thomas at intevation.de
Tue Feb 12 06:23:54 CST 2013
* Bryan O'Sullivan <bos at serpentine.com> [20130212 01:16]:
> # HG changeset patch
> # User Bryan O'Sullivan <bryano at fb.com>
> # Date 1360628112 28800
> # Node ID 4034b8d551b116b882920466e1d209e475a62721
> # Parent f12804d3ff801b989cb2aab1aad93047a8db46f1
> scmutil: create directories in a race-safe way during update
> +def ensuredirs(name, mode=None):
> + """race-safe recursive directory creation"""
> + try:
> + makedirs(name, mode)
> + except OSError, err:
> + if err.errno == errno.EEXIST and os.path.isdir(name):
> + # someone else seems to have won a directory creation race
> + return
> + raise
> +
This is not completely race-safe as makedirs uses recursion, which
can abort too early when one worker is much faster than the other:
Concurrent runs of ensuredirs('a/b/c') and ensuredirs('a/b/d'),
initially 'a' does not exist:
Worker 1: | Worker 2:
---------------------------------+----------------------------
mkdir1('a/b/c') | mkdir1('a/b/d')
-> ENOENT | -> ENOENT
makedirs('a/b') |
mkdir1('a/b') |
-> ENOENT |
| makedirs('a/b')
| mkdir1('a/b')
| -> ENOENT
| makedirs('a')
| mkdir1('a')
| -> OK
| mkdir2('a/b')
| -> OK
| mkdir2('d')
makedirs('a') |
mkdir2('a/b') |
-> EEXIST |
mkdir2('a/b/c') is not executed! |
OSError with EEXIST is raised. |
mkdir1 is the call to os.mkdir in the try part of makedirs(), mkdir2
is the call in the except part.
Regards,
Thomas
--
thomas at intevation.de - http://intevation.de/~thomas/ - OpenPGP key: 0x5816791A
Intevation GmbH, Neuer Graben 17, 49074 Osnabrueck - AG Osnabrueck, HR B 18998
Geschaeftsfuehrer: Frank Koormann, Bernhard Reiter, Dr. Jan-Oliver Wagner
More information about the Mercurial-devel
mailing list