Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
Bug 836400 - portage does not merge package symlinks atomically (util.movefile claims to be atomic but is not)
Summary: portage does not merge package symlinks atomically (util.movefile claims to b...
Alias: None
Product: Portage Development
Classification: Unclassified
Component: Core (show other bugs)
Hardware: All Linux
: Normal normal (vote)
Assignee: Portage team
Keywords: InVCS
Depends on: 837899
Blocks: 563614 835380
  Show dependency tree
Reported: 2022-03-30 07:21 UTC by SpanKY
Modified: 2023-12-24 18:01 UTC (History)
2 users (show)

See Also:
Package list:
Runtime testing required: ---


Note You need to log in before you can comment on or make changes to this bug.
Description SpanKY gentoo-dev 2022-03-30 07:21:14 UTC
from lib/portage/util/
def movefile(...):
  """... Move is atomic."""

but then it does:
    if destexists:
        if stat.S_ISLNK(dstat[stat.ST_MODE]):
>>              os.unlink(dest)
                destexists = 0
    if stat.S_ISLNK(sstat[stat.ST_MODE]):
            target = os.readlink(src)
            if mysettings and "D" in mysettings and target.startswith(mysettings["D"]):
                target = target[len(mysettings["D"]) - 1 :]
            if destexists and not stat.S_ISDIR(dstat[stat.ST_MODE]):
>>              os.unlink(dest)
                if selinux_enabled:
>>                  selinux.symlink(target, dest, src)
>>                  os.symlink(target, dest)

that is by definition not atomic.  when merging a package, there's a small window where the symlink doesn't exist, so anyone using that symlink (e.g. a symlink to a program) can break.  it's a small window, but on loaded systems running a lot of things in parallel, it's not that small.  we're seeing this flake in CrOS builders on a semi-regular basis.  bug 563614 might be an example of this that i misattributed to binutils-config.

it's not clear why this code is deleting the symlink in the first place.  POSIX says that rename supports moving symlinks over symlinks, symlinks over files, and files over symlinks:

so this code should try os.rename first like it does with files, and if that fails (e.g. EXDEV), fallback to the same method as files where it creates a unique name in the same fs and then renames from there.
Comment 1 Larry the Git Cow gentoo-dev 2022-04-15 02:46:25 UTC
The bug has been referenced in the following commit(s):

commit fa82725ba03ffa5edf0b82db7307c87fc97e83f2
Author:     Mike Frysinger <>
AuthorDate: 2022-03-30 06:32:07 +0000
Commit:     Sam James <>
CommitDate: 2022-04-15 02:46:19 +0000

    movefile: merge symlinks atomically
    Since POSIX allows renaming symlinks with symlinks, use that to get
    atomic updates.  This is faster and less flaky to parallel processes:
    removing a live symlink and then recreating it leaves a small window
    where other things might try to use it but fail.
    [sam: cherry-picked from chromiumos' third_party/portage_tool repo]
    (cherry picked from commit cherry-pick 80ed2dac95db81acac8043e6685d0a853a08d268)
    Signed-off-by: Sam James <>
    Signed-off-by: Sam James <>

 lib/portage/util/ | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)