summaryrefslogtreecommitdiffstats
path: root/meta
diff options
context:
space:
mode:
authorRichard Purdie <richard.purdie@linuxfoundation.org>2021-06-30 13:02:25 +0100
committerRichard Purdie <richard.purdie@linuxfoundation.org>2021-07-10 22:46:19 +0100
commita235d64226b96979c8b89ddac2c31819992235fd (patch)
treecd4f90f6e1f25e10075687c28090d4ac84d74c61 /meta
parent522be6c4bffc907278bcc9f29a671d59070c2c2b (diff)
downloadpoky-a235d64226b96979c8b89ddac2c31819992235fd.tar.gz
sstate/staging: Handle directory creation race issue
The sstate code tries to be careful about racing around directory creation. In particular, the copyhardlinktree code creates the directory tree first allowing for "already exists" errors and ignoring them, then hardlinks the files in. Unfortunately the sstate removal code can race against this since it will try and remove empty directories. If there is some bad timing, a newly created directory can be removed before it was populated, leading to build failures. We could try and add locking but this would damage performance, we've been there before. It is also unclear where to actually place locks just based on the contents of a manifest file which may cover multiple sstate install locations for a given task. Instead, lets disable directory removal in the problematic "shared" core path. This could result in a few more empty directories being left on disk but those should be harmless and better than locking hurting performance or rare build races. [YOCTO #13999] [YOCTO #14379] (From OE-Core rev: fa49622521b6386d8031b1e7519f087aa9d99b19) Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org> (cherry picked from commit 4f94d9296394bc7ce241439f00df86eb5912875f) Signed-off-by: Steve Sakoman <steve@sakoman.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta')
-rw-r--r--meta/classes/sstate.bbclass8
-rw-r--r--meta/classes/staging.bbclass6
2 files changed, 8 insertions, 6 deletions
diff --git a/meta/classes/sstate.bbclass b/meta/classes/sstate.bbclass
index 53dcfc8274..9ed0e0c139 100644
--- a/meta/classes/sstate.bbclass
+++ b/meta/classes/sstate.bbclass
@@ -483,7 +483,7 @@ def sstate_clean_cachefiles(d):
483 ss = sstate_state_fromvars(ld, task) 483 ss = sstate_state_fromvars(ld, task)
484 sstate_clean_cachefile(ss, ld) 484 sstate_clean_cachefile(ss, ld)
485 485
486def sstate_clean_manifest(manifest, d, prefix=None): 486def sstate_clean_manifest(manifest, d, canrace=False, prefix=None):
487 import oe.path 487 import oe.path
488 488
489 mfile = open(manifest) 489 mfile = open(manifest)
@@ -501,7 +501,9 @@ def sstate_clean_manifest(manifest, d, prefix=None):
501 if entry.endswith("/"): 501 if entry.endswith("/"):
502 if os.path.islink(entry[:-1]): 502 if os.path.islink(entry[:-1]):
503 os.remove(entry[:-1]) 503 os.remove(entry[:-1])
504 elif os.path.exists(entry) and len(os.listdir(entry)) == 0: 504 elif os.path.exists(entry) and len(os.listdir(entry)) == 0 and not canrace:
505 # Removing directories whilst builds are in progress exposes a race. Only
506 # do it in contexts where it is safe to do so.
505 os.rmdir(entry[:-1]) 507 os.rmdir(entry[:-1])
506 else: 508 else:
507 os.remove(entry) 509 os.remove(entry)
@@ -539,7 +541,7 @@ def sstate_clean(ss, d):
539 for lock in ss['lockfiles']: 541 for lock in ss['lockfiles']:
540 locks.append(bb.utils.lockfile(lock)) 542 locks.append(bb.utils.lockfile(lock))
541 543
542 sstate_clean_manifest(manifest, d) 544 sstate_clean_manifest(manifest, d, canrace=True)
543 545
544 for lock in locks: 546 for lock in locks:
545 bb.utils.unlockfile(lock) 547 bb.utils.unlockfile(lock)
diff --git a/meta/classes/staging.bbclass b/meta/classes/staging.bbclass
index 506ce0665e..78eb914921 100644
--- a/meta/classes/staging.bbclass
+++ b/meta/classes/staging.bbclass
@@ -408,7 +408,7 @@ python extend_recipe_sysroot() {
408 if os.path.islink(f) and not os.path.exists(f): 408 if os.path.islink(f) and not os.path.exists(f):
409 bb.note("%s no longer exists, removing from sysroot" % f) 409 bb.note("%s no longer exists, removing from sysroot" % f)
410 lnk = os.readlink(f.replace(".complete", "")) 410 lnk = os.readlink(f.replace(".complete", ""))
411 sstate_clean_manifest(depdir + "/" + lnk, d, workdir) 411 sstate_clean_manifest(depdir + "/" + lnk, d, canrace=True, prefix=workdir)
412 os.unlink(f) 412 os.unlink(f)
413 os.unlink(f.replace(".complete", "")) 413 os.unlink(f.replace(".complete", ""))
414 414
@@ -453,7 +453,7 @@ python extend_recipe_sysroot() {
453 fl = depdir + "/" + l 453 fl = depdir + "/" + l
454 bb.note("Task %s no longer depends on %s, removing from sysroot" % (mytaskname, l)) 454 bb.note("Task %s no longer depends on %s, removing from sysroot" % (mytaskname, l))
455 lnk = os.readlink(fl) 455 lnk = os.readlink(fl)
456 sstate_clean_manifest(depdir + "/" + lnk, d, workdir) 456 sstate_clean_manifest(depdir + "/" + lnk, d, canrace=True, prefix=workdir)
457 os.unlink(fl) 457 os.unlink(fl)
458 os.unlink(fl + ".complete") 458 os.unlink(fl + ".complete")
459 459
@@ -474,7 +474,7 @@ python extend_recipe_sysroot() {
474 continue 474 continue
475 else: 475 else:
476 bb.note("%s exists in sysroot, but is stale (%s vs. %s), removing." % (c, lnk, c + "." + taskhash)) 476 bb.note("%s exists in sysroot, but is stale (%s vs. %s), removing." % (c, lnk, c + "." + taskhash))
477 sstate_clean_manifest(depdir + "/" + lnk, d, workdir) 477 sstate_clean_manifest(depdir + "/" + lnk, d, canrace=True, prefix=workdir)
478 os.unlink(depdir + "/" + c) 478 os.unlink(depdir + "/" + c)
479 if os.path.lexists(depdir + "/" + c + ".complete"): 479 if os.path.lexists(depdir + "/" + c + ".complete"):
480 os.unlink(depdir + "/" + c + ".complete") 480 os.unlink(depdir + "/" + c + ".complete")