Skip to content

[Bug] Python package stubs crash when the same command runs in parallel #367

Closed

Description

@cfgnunes

Running the same pkgx Python command in parallel crashes. The bin/ stub rewrites the shared virtualenv on every invocation, with no lock, and then executes the real script.

This problem showed up with github.com/0xabu/pdfannots. The stub is ~/.pkgx/github.com/0xabu/pdfannots/v0.5.0/bin/pdfannots.

On every run the stub:

  1. Rewrites venv/pyvenv.cfg.
  2. Opens every file in venv/bin/ with rb+ and rewrites shebangs that end in python.
  3. Deletes venv/bin/python and creates the symlink again.
  4. Calls os.execv on venv/bin/pdfannots.

A single process is fine, because the rewrite finishes before the next start. With several processes, they mutate those same files together. Typical failures:

OSError: [Errno 26] Text file busy
  File ".../bin/pdfannots", line 50, in <module>
    os.execv(arg0, args)

FileExistsError: [Errno 17] File exists: '.../python.org/v3.15.0/bin/python' -> '.../venv/bin/python'
  File ".../bin/pdfannots", line 43, in <module>
    os.symlink(python_path, python_symlink)

FileNotFoundError: [Errno 2] No such file or directory: '.../venv/bin/python'
  File ".../bin/pdfannots", line 41, in <module>
    os.remove(python_symlink)

Reproduction:

seq 8 | xargs -P 8 -I{} pkgx pdfannots --version

One process at a time prints pdfannots 0.5. Eight at a time intermittently hit the errors above. The same pattern should affect any pkgx Python package whose bin/ entry uses this stub.

Expected behavior: concurrent invocations of an already installed package should not rewrite the virtualenv. The stub can prepare the venv once, or skip the rewrite when pyvenv.cfg and venv/bin/python already point at the current interpreter.

Activity

  1. cfgnunes commented on Oct 16, 2026

    @cfgnunes
    ContributorAuthor

    Hey @jhheider, do you have any ideas on how to fix this issue? I'm not even sure where the fix belongs... in pantry or in the pkgx repository itself. Any pointers would be appreciated!!

  2. transferred this issue frompkgxdev/pantryon Oct 16, 2026
  3. jhheider commented on Oct 16, 2026

    @jhheider
    Contributor

    bkpyvenv is the culprit here. it's not race-safe. using a lockfile or checking if the stub needs rewrites before rewriting would be better. happy to take a PR, or I'll look into it.

  4. jhheider commented on Oct 16, 2026

    @jhheider
    Contributor

    even a simple .stamp that contains the path it was rewritten for would tell it if it needed to be rewritten again. possibly including the python path.

  5. cfgnunes commented on Oct 16, 2026

    @cfgnunes
    ContributorAuthor

    @jhheider thanks for the feedback!

    I've written a fix that I believe should solve this issue in PR: #368

    Could you take a look and let me know if everything looks good?

  6. jhheider commented on Oct 16, 2026

    @jhheider
    Contributor

    Fixed by #368, released in brewkit v1.23.3 and published to the pantry: https://github.com/pkgxdev/pantry/actions/runs/38979727618

    I rebuilt github.com/0xabu/pdfannots 0.5.0 with it: https://github.com/pkgxdev/pantry/actions/runs/38980171025

    Checked against a fresh PKGX_DIR with the rebuilt bottle: seq 16 | xargs -P 16 -I{} pkgx pdfannots --version, three rounds, gave 48 of 48 pdfannots 0.5 and no errors. The stub now takes an flock on the venv's bin/ directory and only rewrites when the interpreter or a shebang is stale, so a current venv is never written to.

  7. cfgnunes commented on Oct 16, 2026

    @cfgnunes
    ContributorAuthor

    Thanks for the quick fix and for being so responsive @jhheider ! You're almost like the superhero The Flash, incredibly fast! 😄

    I've tested it here, and everything worked perfectly. Thanks again for the great work!

  8. jhheider commented on Oct 16, 2026

    @jhheider
    Contributor

    thanks for the diagnosis and the shape the fix!

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