summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Purdie <richard.purdie@linuxfoundation.org>2013-05-03 15:11:33 +0100
committerRichard Purdie <richard.purdie@linuxfoundation.org>2013-05-03 16:12:24 +0100
commit2f954a9a6932f1e6c564e7e7aacaac628a75eed7 (patch)
treeffb8828647ceab518280a4e48a2e0f5fb4e7797c
parentf1854e458e5e77806b1fc837033500fa91272261 (diff)
downloadopenembedded-core-2f954a9a6932f1e6c564e7e7aacaac628a75eed7.tar.gz
openembedded-core-2f954a9a6932f1e6c564e7e7aacaac628a75eed7.tar.bz2
openembedded-core-2f954a9a6932f1e6c564e7e7aacaac628a75eed7.zip
path.py: Deal with race issue
The change to use copyhardlinktree in some of the sstate code instead of copytree exposed a race condition. This is due to cp failing if it finds a directory doesn't exist yet some other process creates it while cp was trying to create it itself. tar doesn't error in this case. To fix this we need to create the directory structure with tar, then use cp to hardlink the files. Messy but probably worth doing. I also took the opportunity to remove src_bak since the code is neater without it. Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--meta/lib/oe/path.py18
1 files changed, 11 insertions, 7 deletions
diff --git a/meta/lib/oe/path.py b/meta/lib/oe/path.py
index 4f8b66c2f3..76a6ed8314 100644
--- a/meta/lib/oe/path.py
+++ b/meta/lib/oe/path.py
@@ -87,16 +87,20 @@ def copytree(src, dst):
def copyhardlinktree(src, dst):
""" Make the hard link when possible, otherwise copy. """
bb.utils.mkdirhier(dst)
- src_bak = src
- if os.path.isdir(src):
- if not len(os.listdir(src)):
- return
- src = src + "/*"
- if (os.stat(src_bak).st_dev == os.stat(dst).st_dev):
+ if os.path.isdir(src) and not len(os.listdir(src)):
+ return
+
+ if (os.stat(src).st_dev == os.stat(dst).st_dev):
+ # Need to copy directories only with tar first since cp will error if two
+ # writers try and create a directory at the same time
+ cmd = 'cd %s; find . -type d -print | tar -cf - -C %s -ps --files-from - | tar -xf - -C %s' % (src, src, dst)
+ check_output(cmd, shell=True, stderr=subprocess.STDOUT)
+ if os.path.isdir(src):
+ src = src + "/*"
cmd = 'cp -afl %s %s' % (src, dst)
check_output(cmd, shell=True, stderr=subprocess.STDOUT)
else:
- copytree(src_bak, dst)
+ copytree(src, dst)
def remove(path, recurse=True):
"""Equivalent to rm -f or rm -rf"""