Skip to content

Scope the llama.cpp update test's Popen patch to the installer - #10105

Merged
danielhanchen merged 3 commits into
mainfrom
fix/llama-update-test-popen-scope
Sep 1, 2026
Merged

danielhanchen merged 3 commits into
mainfrom
fix/llama-update-test-popen-scope

Conversation

@danielhanchen

Copy link
Copy Markdown
Member

test_start_update_happy_path fails on macOS, and has since 2026-08-09:

AssertionError: assert '--install-dir' in ['ps', '-o', 'lstart=,comm=', '-p', '2770']

The update itself is fine. The same run logs the installer starting with the right arguments and finishing on the new tag:

llama update: installing  cmd='... install_llama_prebuilt.py --install-dir .../llama.cpp --llama-tag latest --published-repo unslothai/llama.cpp'
llama update: success     backend=None to_tag=b9518

Only the assertion is wrong.

What happens

_patch_installer_popen does monkeypatch.setattr(upd.subprocess, "Popen", ...). subprocess is a shared module object, so that replaces Popen for the whole process and the double fires on_start for every spawn. on_start writes captured["cmd"] = cmd, last one wins.

That was harmless when the phase spawned exactly one thing. #8170 changed it: _run_llama_phase now calls adopt_pid(proc.pid) right after starting the installer, which reaches process_lifetime._pid_identity. On Linux that reads /proc/<pid>/stat and spawns nothing, so the test passes. macOS has no /proc and shells out to ps -o lstart=,comm= -p <pid>, a second spawn, after the installer, which overwrites the capture.

what commit PR date
the test dab0b7767 #6097 2026-06-10
the process-wide Popen patch b2b1dcd6a #6196 2026-06-11
adopt_pid plus the macOS ps branch c6ad59a7d #8170 2026-08-09

Nothing in CI runs studio/backend/tests/ on macOS, so this only ever showed up running the suite locally on a Mac.

Why the test, and not the code

adopt_pid and the ps identity check are right. A recorded pid has to be provably the same process before anything signals it, and on macOS ps -o lstart= is the only cheap source of that. Nothing there should change to suit a test double.

The fix is also already in the tree. _patch_llama_installer in test_combined_update.py gates on the installer command, added in #7095, a month before #8170 landed:

# Only intercept the installer invocation: importing routes.inference inside
# the worker can Popen unrelated host probes (ldconfig etc).
is_installer = any("install_llama_prebuilt" in str(part) for part in cmd)

test_llama_cpp_update.py never got the same treatment. This applies it.

Changes

  • _patch_installer_popen only fires on_start and captured_kwargs for the installer command.
  • _FakeInstallerPopen gains __enter__ / __exit__. subprocess.run uses with Popen(...), so without them a non-installer call raised AttributeError into _pid_identity's bare except Exception: return None, silently disabling the identity check the fake had just intercepted.
  • The helper can record every spawned argv, not just the last one. Last-wins capture is what let this hide for two months.
  • A regression test that forces the macOS branch on a Linux host, so this is covered where CI actually runs.

No product code is touched.

Verification

On main, with process_lifetime.sys.platform forced to darwin:

1 failed, 56 passed

After the change, forced and unforced:

57 passed

The new test was run against main's unfixed helper first and fails there, so it is not a test that passes either way. It also asserts a ps spawn actually happened, so a green run cannot come from never reaching the ordering it guards.

test_llama_cpp_update.py, test_combined_update.py and test_orphaned_children.py together: 190 passed, 1 skipped.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 1, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-01T01:10:18.120510Z be6458d Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: dd03599434

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +62 to +65
# subprocess.run() uses `with Popen(...)`, and without these it raises into
# _pid_identity's bare except, silently disabling the identity check.
def __enter__(self):
return self

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Complete the fake Popen protocol for subprocess.run

When this helper intercepts the forced macOS ps lookup, subprocess.run() calls process.communicate(...) after entering the context, but _FakeInstallerPopen still has no communicate method or args attribute. The resulting AttributeError is swallowed by process_lifetime._pid_identity, so the new test only proves that construction of the ps process was attempted while silently disabling the identity lookup it claims to exercise. Implement the remaining protocol with representative ps output, or delegate non-installer commands to the original Popen, so failures after that spawn cannot remain hidden.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct, and it undercut the claim I made in the description. Fixed in be6458d.

Reproduced it directly: driving subprocess.run through the double raises AttributeError: '_FakeInstallerPopen' object has no attribute 'communicate', so __enter__/__exit__ alone were not enough and _pid_identity was still swallowing the failure.

Took the delegation option rather than growing the fake, since a stand-in owes subprocess.run the whole protocol and the next missing method would fail the same silent way. That also matches the dominant idiom in this suite (_REAL_POPEN bound at module scope, filter on the command, delegate the rest, as in test_llama_cpp_placement.py). __enter__/__exit__ are gone again, since only the installer sees the fake now and that path uses Popen directly.

The regression test also asserts the lookup completes rather than merely starts:

assert process_lifetime._pid_identity(os.getpid()), "the ps lookup did not complete"

@danielhanchen

Copy link
Copy Markdown
Member Author

@codex review

1 similar comment
@danielhanchen

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Already looking forward to the next diff.

Reviewed commit: be6458d028

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@danielhanchen
danielhanchen merged commit 454a5ab into main Sep 1, 2026
33 of 34 checks passed
@danielhanchen
danielhanchen deleted the fix/llama-update-test-popen-scope branch September 1, 2026 01:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant