Skip to content

fix(evals): build rust oracle binary once and exec directly to end cargo-run link race#751

Merged
vitali87 merged 3 commits into
mainfrom
fix/rust-oracle-build-race
Jul 14, 2026
Merged

fix(evals): build rust oracle binary once and exec directly to end cargo-run link race#751
vitali87 merged 3 commits into
mainfrom
fix/rust-oracle-build-race

Conversation

@vitali87

Copy link
Copy Markdown
Owner

Problem

Six Rust-oracle test files (test_rust_containment_oracle, test_rust_structure_oracle, test_rust_closure_containment_oracle, test_rust_inheritance_oracle, test_rust_span_oracle, test_rust_external_impl_containment_oracle) each shelled out to cargo run against the same shared evals/oracles/rs_oracle manifest, so all built/linked the same target/release/rs_oracle binary. Under pytest -n auto on a cold CI runner, concurrent workers raced that link step: one worker exec'd the binary while another relinked it (ETXTBSY), and cargo exited 101.

Observed as an intermittent red on the macos-py3.12 runner (passed on the four other runners and locally); a re-run went green, which is the signature of this race rather than a code fault.

Fix

  • _ensure_oracle_built() builds the syn oracle binary exactly once, serialized across pytest-xdist workers by a filelock cross-process lock, then all callers exec the prebuilt binary directly instead of via cargo run. A prebuilt binary is only ever read afterwards, so concurrent execs are safe.
  • _binary_path() resolves the real output path via cargo metadata rather than hardcoding target/release/, because a user/global cargo config or CARGO_TARGET_DIR can redirect it (e.g. the common macOS build.target-dir = "target.noindex" Spotlight workaround). Memoized, read-only, no build/link.
  • An mtime guard still rebuilds when the oracle source changes (local-dev correctness).
  • filelock promoted from transitive to an explicit test dependency; .build.lock gitignored.

Go's oracle uses go run (per-invocation temp binary), so it has no shared-path race and is unaffected.

Tests

  • New test_rust_oracle_build_once.py pins the contract: build once, never cargo run, exec the binary directly. Verified RED against the old cargo run code.
  • New test + all 6 real oracle tests pass on a cold target/ under 8 workers, across repeated cold-build loops; mtime-rebuild path verified.
  • Full suite: 5131 passed, 19 skipped. ruff / ruff-format / ty / pre-commit hooks all pass.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request resolves a race condition in the Rust oracle execution during parallel test runs by ensuring the binary is built exactly once and then executed directly, rather than using cargo run repeatedly. It introduces a cross-process file lock (filelock) to serialize the build step, queries the binary path dynamically via cargo metadata, and adds a dedicated test to verify this behavior. The review feedback recommends catching json.JSONDecodeError when parsing subprocess outputs (both for cargo metadata and the oracle payload) and raising a RuntimeError with stdout and stderr to improve error visibility.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread evals/oracles/rust_oracle.py Outdated
Comment on lines +48 to +49
target_dir = Path(json.loads(proc.stdout)[ec.CARGO_META_TARGET_DIR_KEY])
return target_dir / ec.CARGO_RELEASE_DIRNAME / ec.RS_ORACLE_BIN

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

When capturing subprocess output and parsing it as JSON, we should catch json.JSONDecodeError and raise a RuntimeError containing both stdout and stderr. This ensures that any underlying cargo or compilation errors are surfaced clearly instead of a context-free JSON decode failure.

Suggested change
target_dir = Path(json.loads(proc.stdout)[ec.CARGO_META_TARGET_DIR_KEY])
return target_dir / ec.CARGO_RELEASE_DIRNAME / ec.RS_ORACLE_BIN
try:
target_dir = Path(json.loads(proc.stdout)[ec.CARGO_META_TARGET_DIR_KEY])
except json.JSONDecodeError as e:
raise RuntimeError(
f"Failed to parse cargo metadata JSON.\nStdout: {proc.stdout}\nStderr: {proc.stderr}"
) from e
return target_dir / ec.CARGO_RELEASE_DIRNAME / ec.RS_ORACLE_BIN
References
  1. When capturing subprocess output and parsing it as JSON, catch json.JSONDecodeError and raise a RuntimeError containing both stdout and stderr to ensure underlying errors are surfaced.

Comment on lines 94 to 95
payload: OraclePayload = json.loads(proc.stdout or "{}")
return payload

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

When capturing subprocess output and parsing it as JSON, we should catch json.JSONDecodeError and raise a RuntimeError containing both stdout and stderr. This ensures that any underlying execution errors are surfaced clearly instead of a context-free JSON decode failure.

Suggested change
payload: OraclePayload = json.loads(proc.stdout or "{}")
return payload
try:
payload: OraclePayload = json.loads(proc.stdout or "{}")
except json.JSONDecodeError as e:
raise RuntimeError(
f"Failed to parse oracle payload JSON.\nStdout: {proc.stdout}\nStderr: {proc.stderr}"
) from e
return payload
References
  1. When capturing subprocess output and parsing it as JSON, catch json.JSONDecodeError and raise a RuntimeError containing both stdout and stderr to ensure underlying errors are surfaced.

@greptile-apps

greptile-apps Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR changes the Rust oracle runner to avoid concurrent cargo run link races. The main changes are:

  • Builds the Rust oracle binary once behind a filelock lock.
  • Resolves the Cargo release binary path through cargo metadata.
  • Executes the prebuilt binary directly for each oracle payload request.
  • Adds tests for the build-once contract and platform executable suffix handling.
  • Declares filelock as an explicit test dependency and ignores the local build lock file.

Confidence Score: 5/5

Safe to merge with minimal risk.

No issues were found in the changed paths. The update preserves configurable Cargo target directories, handles the Windows executable suffix, and adds focused tests for the new runner behavior.

No files require special attention.

T-Rex T-Rex Logs

What T-Rex did

  • Verified the Pytest blocker proof shows the exact requested command, working directory, dependency error, and exit code 4.
  • Verified the Cargo metadata proof confirms the metadata command exited with code 0 and reveals the resolved Cargo target directory.
  • Verified the Cargo build proof confirms the release build command exited with code 0.
  • Verified the direct execution proof shows the script derived the release binary path from cargo metadata, the binary exists, and the program runs with --help and exits with code 0.

View all artifacts

T-Rex Ran code and verified through T-Rex

Important Files Changed

Filename Overview
.gitignore Adds the Rust oracle build lock file to ignored artifacts so local serialized builds do not dirty the worktree.
codebase_rag/tests/test_rust_oracle_build_once.py Adds tests asserting the Rust oracle builds once, never uses cargo run, execs the binary directly, and preserves the Windows executable suffix.
evals/constants.py Centralizes Rust oracle command, binary, suffix, metadata, and source-glob constants used by the new build path.
evals/oracles/rust_oracle.py Replaces per-call cargo run with a file-lock-serialized release build, Cargo metadata-based binary resolution, source mtime rebuild guard, and direct binary execution.
pyproject.toml Promotes filelock to an explicit test extra dependency for the Rust oracle build lock.
uv.lock Updates package metadata and lock entries to include filelock in the test extra.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant Test as Rust oracle caller
participant Runner as rust_oracle.py
participant Cargo as cargo metadata/build
participant Lock as .build.lock
participant Binary as rs_oracle binary

Test->>Runner: _run_rust_oracle_payload(target)
Runner->>Cargo: cargo metadata --no-deps --manifest-path Cargo.toml
Cargo-->>Runner: target_directory
Runner->>Lock: acquire FileLock
alt binary missing or sources newer
    Runner->>Cargo: cargo build --release -q --manifest-path Cargo.toml
    Cargo-->>Binary: writes release binary
end
Runner->>Lock: release FileLock
Runner->>Binary: exec binary target
Binary-->>Runner: JSON payload
Runner-->>Test: OraclePayload
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant Test as Rust oracle caller
participant Runner as rust_oracle.py
participant Cargo as cargo metadata/build
participant Lock as .build.lock
participant Binary as rs_oracle binary

Test->>Runner: _run_rust_oracle_payload(target)
Runner->>Cargo: cargo metadata --no-deps --manifest-path Cargo.toml
Cargo-->>Runner: target_directory
Runner->>Lock: acquire FileLock
alt binary missing or sources newer
    Runner->>Cargo: cargo build --release -q --manifest-path Cargo.toml
    Cargo-->>Binary: writes release binary
end
Runner->>Lock: release FileLock
Runner->>Binary: exec binary target
Binary-->>Runner: JSON payload
Runner-->>Test: OraclePayload
Loading

Reviews (2): Last reviewed commit: "fix(evals): resolve rust oracle binary w..." | Re-trigger Greptile

Comment thread evals/oracles/rust_oracle.py Outdated
@vitali87

Copy link
Copy Markdown
Owner Author

@greptile review

@vitali87
vitali87 merged commit 23c9ab4 into main Jul 14, 2026
20 of 21 checks passed
@vitali87
vitali87 deleted the fix/rust-oracle-build-race branch July 14, 2026 12:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant