All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Steve Sakoman" <steve@sakoman.com>
To: openembedded-core@lists.openembedded.org
Subject: [OE-core][dunfell 17/19] sstate/staging: Handle directory creation race issue
Date: Mon,  5 Jul 2021 12:34:54 -1000	[thread overview]
Message-ID: <cca936fb9e8ecbdd08ec6b0d7de43df5c2bb2323.1625511812.git.steve@sakoman.com> (raw)
In-Reply-To: <cover.1625511812.git.steve@sakoman.com>

From: Richard Purdie <richard.purdie@linuxfoundation.org>

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]

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
(cherry picked from commit 4f94d9296394bc7ce241439f00df86eb5912875f)
Signed-off-by: Steve Sakoman <steve@sakoman.com>
---
 meta/classes/sstate.bbclass  | 8 +++++---
 meta/classes/staging.bbclass | 6 +++---
 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):
         ss = sstate_state_fromvars(ld, task)
         sstate_clean_cachefile(ss, ld)
 
-def sstate_clean_manifest(manifest, d, prefix=None):
+def sstate_clean_manifest(manifest, d, canrace=False, prefix=None):
     import oe.path
 
     mfile = open(manifest)
@@ -501,7 +501,9 @@ def sstate_clean_manifest(manifest, d, prefix=None):
             if entry.endswith("/"):
                 if os.path.islink(entry[:-1]):
                     os.remove(entry[:-1])
-                elif os.path.exists(entry) and len(os.listdir(entry)) == 0:
+                elif os.path.exists(entry) and len(os.listdir(entry)) == 0 and not canrace:
+                    # Removing directories whilst builds are in progress exposes a race. Only
+                    # do it in contexts where it is safe to do so.
                     os.rmdir(entry[:-1])
             else:
                 os.remove(entry)
@@ -539,7 +541,7 @@ def sstate_clean(ss, d):
         for lock in ss['lockfiles']:
             locks.append(bb.utils.lockfile(lock))
 
-        sstate_clean_manifest(manifest, d)
+        sstate_clean_manifest(manifest, d, canrace=True)
 
         for lock in locks:
             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() {
         if os.path.islink(f) and not os.path.exists(f):
             bb.note("%s no longer exists, removing from sysroot" % f)
             lnk = os.readlink(f.replace(".complete", ""))
-            sstate_clean_manifest(depdir + "/" + lnk, d, workdir)
+            sstate_clean_manifest(depdir + "/" + lnk, d, canrace=True, prefix=workdir)
             os.unlink(f)
             os.unlink(f.replace(".complete", ""))
 
@@ -453,7 +453,7 @@ python extend_recipe_sysroot() {
             fl = depdir + "/" + l
             bb.note("Task %s no longer depends on %s, removing from sysroot" % (mytaskname, l))
             lnk = os.readlink(fl)
-            sstate_clean_manifest(depdir + "/" + lnk, d, workdir)
+            sstate_clean_manifest(depdir + "/" + lnk, d, canrace=True, prefix=workdir)
             os.unlink(fl)
             os.unlink(fl + ".complete")
 
@@ -474,7 +474,7 @@ python extend_recipe_sysroot() {
                 continue
             else:
                 bb.note("%s exists in sysroot, but is stale (%s vs. %s), removing." % (c, lnk, c + "." + taskhash))
-                sstate_clean_manifest(depdir + "/" + lnk, d, workdir)
+                sstate_clean_manifest(depdir + "/" + lnk, d, canrace=True, prefix=workdir)
                 os.unlink(depdir + "/" + c)
                 if os.path.lexists(depdir + "/" + c + ".complete"):
                     os.unlink(depdir + "/" + c + ".complete")
-- 
2.25.1


  parent reply	other threads:[~2021-07-05 22:37 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-05 22:34 [OE-core][dunfell 00/19] Patch review Steve Sakoman
2021-07-05 22:34 ` [OE-core][dunfell 01/19] python3: skip tests requiring tools-sdk Steve Sakoman
2021-07-05 22:34 ` [OE-core][dunfell 02/19] python3: apply test skipping patch unconditionally Steve Sakoman
2021-07-05 22:34 ` [OE-core][dunfell 03/19] rpm: fix CVE-2021-3421 Steve Sakoman
2021-07-05 22:34 ` [OE-core][dunfell 04/19] gstreamer-plugins-base: fix CVE-2021-3522 Steve Sakoman
2021-07-05 22:34 ` [OE-core][dunfell 05/19] linux-yocto/5.4: update to v5.4.124 Steve Sakoman
2021-07-05 22:34 ` [OE-core][dunfell 06/19] linux-yocto/5.4: update to v5.4.125 Steve Sakoman
2021-07-05 22:34 ` [OE-core][dunfell 07/19] linux-yocto/5.4: update to v5.4.128 Steve Sakoman
2021-07-05 22:34 ` [OE-core][dunfell 08/19] linux-yocto/5.4: update to v5.4.129 Steve Sakoman
2021-07-05 22:34 ` [OE-core][dunfell 09/19] kernel: Fix interaction when packaging disabled Steve Sakoman
2021-07-05 22:34 ` [OE-core][dunfell 10/19] kernel-devicetree: " Steve Sakoman
2021-07-05 22:34 ` [OE-core][dunfell 11/19] selftest: do not hardcode /tmp/sdk Steve Sakoman
2021-07-05 22:34 ` [OE-core][dunfell 12/19] perf: Use python3targetconfig to ensure we use target libraries Steve Sakoman
2021-07-05 22:34 ` [OE-core][dunfell 13/19] pypi: set SRC_URI with _prepend, not with += Steve Sakoman
2021-07-06  8:30   ` Martin Jansa
2021-07-06  8:41     ` Khem Raj
2021-07-06 14:16     ` Steve Sakoman
2021-07-05 22:34 ` [OE-core][dunfell 14/19] package_pkgdata: Avoid task hash mismatches for generic task changes Steve Sakoman
2021-07-05 22:34 ` [OE-core][dunfell 15/19] sstate.bbclass: fix errors about read-only sstate mirrors Steve Sakoman
2021-07-05 22:34 ` [OE-core][dunfell 16/19] oeqa/selftest/runcmd: Tweal test timeouts Steve Sakoman
2021-07-05 22:34 ` Steve Sakoman [this message]
2021-07-05 22:34 ` [OE-core][dunfell 18/19] devtool: deploy-target: Fix preserving attributes when using --strip Steve Sakoman
2021-07-05 22:34 ` [OE-core][dunfell 19/19] oeqa/selftest/archiver: Allow tests to ignore empty directories Steve Sakoman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=cca936fb9e8ecbdd08ec6b0d7de43df5c2bb2323.1625511812.git.steve@sakoman.com \
    --to=steve@sakoman.com \
    --cc=openembedded-core@lists.openembedded.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.