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-20 19:05:45 +0100
commita984121558f8d74a263657e29d0bf9d3521dc22f (patch)
treed614a2f47f4e73d7bdf90e242f7b8c74f460da8a /meta
parent5116990224bba57153f457a82e0f8f68aade363d (diff)
downloadpoky-a984121558f8d74a263657e29d0bf9d3521dc22f.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: 3bea0da687d28c80f0b63e2ad81573a3601bb482) Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org> (cherry picked from commit 4f94d9296394bc7ce241439f00df86eb5912875f) Signed-off-by: Anuj Mittal <anuj.mittal@intel.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 3ab6328f91..2b5d94dd1f 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 806a85773a..32a615c743 100644
--- a/meta/classes/staging.bbclass
+++ b/meta/classes/staging.bbclass
@@ -409,7 +409,7 @@ python extend_recipe_sysroot() {
409 if os.path.islink(f) and not os.path.exists(f): 409 if os.path.islink(f) and not os.path.exists(f):
410 bb.note("%s no longer exists, removing from sysroot" % f) 410 bb.note("%s no longer exists, removing from sysroot" % f)
411 lnk = os.readlink(f.replace(".complete", "")) 411 lnk = os.readlink(f.replace(".complete", ""))
412 sstate_clean_manifest(depdir + "/" + lnk, d, workdir) 412 sstate_clean_manifest(depdir + "/" + lnk, d, canrace=True, prefix=workdir)
413 os.unlink(f) 413 os.unlink(f)
414 os.unlink(f.replace(".complete", "")) 414 os.unlink(f.replace(".complete", ""))
415 415
@@ -454,7 +454,7 @@ python extend_recipe_sysroot() {
454 fl = depdir + "/" + l 454 fl = depdir + "/" + l
455 bb.note("Task %s no longer depends on %s, removing from sysroot" % (mytaskname, l)) 455 bb.note("Task %s no longer depends on %s, removing from sysroot" % (mytaskname, l))
456 lnk = os.readlink(fl) 456 lnk = os.readlink(fl)
457 sstate_clean_manifest(depdir + "/" + lnk, d, workdir) 457 sstate_clean_manifest(depdir + "/" + lnk, d, canrace=True, prefix=workdir)
458 os.unlink(fl) 458 os.unlink(fl)
459 os.unlink(fl + ".complete") 459 os.unlink(fl + ".complete")
460 460
@@ -475,7 +475,7 @@ python extend_recipe_sysroot() {
475 continue 475 continue
476 else: 476 else:
477 bb.note("%s exists in sysroot, but is stale (%s vs. %s), removing." % (c, lnk, c + "." + taskhash)) 477 bb.note("%s exists in sysroot, but is stale (%s vs. %s), removing." % (c, lnk, c + "." + taskhash))
478 sstate_clean_manifest(depdir + "/" + lnk, d, workdir) 478 sstate_clean_manifest(depdir + "/" + lnk, d, canrace=True, prefix=workdir)
479 os.unlink(depdir + "/" + c) 479 os.unlink(depdir + "/" + c)
480 if os.path.lexists(depdir + "/" + c + ".complete"): 480 if os.path.lexists(depdir + "/" + c + ".complete"):
481 os.unlink(depdir + "/" + c + ".complete") 481 os.unlink(depdir + "/" + c + ".complete")