Skip to content

Getting PKGBUILD file can fail due to pacman database lock #88

Description

@fergus-dall

When not being run directly on a PKGBUILD, repro runs a short script inside an ephemeral container based on the downloaded chroot. This script involves running pacman -S asp devtools --noconfirm to install tools required to download and validate the PKGBUILD file, which in turn will fail if pacman cannot take the lock on its database.

Early in it's run, repro will also try and update the chroot by running pacman -Syu --noconfirm inside it, which also takes the pacman database lock. In order to guard against this possibility, repro locks the file root.lock before doing this, and skips this step if it's already locked. However, the step above does not try and take this lock, so two instances of repro can try and run these two steps simultaneously.

The fact that the PKGBUILD step is run in an ephemeral container prevents it from damaging the update step, but not vice versa. If the snapshot used by the ephemeral container is taken while the update is in progress, it will include the lock file, and the PKGBUILD step will fail.

This can be seen by doing something like:

for i in {1..20}
do
    CACHEDIR=/path/to/cache repro ./acl-2.2.53-3-x86_64.pkg.tar.zst 2>output-${i} >output-${i} &
    sleep 1
done

Most of the spawned repro instances will fail due to this issue.

Taking a shared lock on root.lock for this step (lines 301-318 in repro.in) solves this issue, and will also prevent issues that may arise from operating in a chroot that is mid-upgrade. This should also be done for the other ephemeral containers used to set up the build chroot, though I haven't actually seen any issues from this yet, probably because chroot updates are relatively rare.

Also related to this lock, when setting up the chroot for the first time, repro attempts to take the lock, but doesn't check if this operation succeeds (line 215). Thus, multiple instances of repro can be trying to install the chroot at the same time. The correct order of operations should be:

if [ ! -d "$BUILDDIRECTORY"/root ]; then
    # block on the lock file
    nlock 9 "$BUILDDIRECTORY"/root.lock
    if [ -d "$BUILDDIRECTORY"/root ]; then
        # chroot was created by someone else, don't need to do anything
        unlock 9
    else
        # set up chroot
    fi
fi

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions