From patchwork Fri Nov 6 16:55:46 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: [STABLE] posix: avoid race condition while checking for symlinking capability From: =?utf-8?q?Mathias_De_Mar=C3=A9?= X-Patchwork-Id: 11303 Message-Id: To: mercurial-devel@selenic.com Date: Fri, 06 Nov 2015 10:55:46 -0600 # HG changeset patch # User Mathias De Maré # Date 1446828659 -3600 # Fri Nov 06 17:50:59 2015 +0100 # Branch stable # Node ID f8ff6c7234fec490e5ab98633bdcabbb403d48a1 # Parent e7c618cee8df35aefedad15b991d628bae1c60c8 posix: avoid race condition while checking for symlinking capability We start several workers (one per core), so it's possible two workers get the same result for 'mktemp'. This can result in one of the workers failing to create a symlink, causing a percentage of the symlinks to be created as regular files. This happens very rarely, but I've seen it occur on a repository with ~6000 symbolic links and with a machine with 32 cores. diff --git a/mercurial/posix.py b/mercurial/posix.py --- a/mercurial/posix.py +++ b/mercurial/posix.py @@ -168,9 +168,8 @@ def checklink(path): """check whether the given path is on a symlink-capable filesystem""" - # mktemp is not racy because symlink creation will fail if the - # file already exists - name = tempfile.mktemp(dir=path, prefix='hg-checklink-') + tmpdir = tempfile.mkdtemp(dir=path, prefix='hg-checklink-') + name = os.path.join(tmpdir, 'link') try: fd = tempfile.NamedTemporaryFile(dir=path, prefix='hg-checklink-') try: @@ -179,6 +178,7 @@ return True finally: fd.close() + os.rmdir(tmpdir) except AttributeError: return False except OSError as inst: