Skip to content

CONTRIBUTING.md: cargo test command segfaults on rustpython-capi #8415

Description

@leehanjeong

Summary

The Rust test command in CONTRIBUTING.md does not match what CI runs. Following it as written segfaults, because rustpython-capi cannot be built correctly from the workspace root.

What happens

On Linux at ede18e44c:

Command Result
cargo test --workspace --exclude rustpython_wasm --exclude rustpython-venvlauncher — as documented exit 101, SIGSEGV
the same plus --exclude rustpython-capi exit 0 — 1093 tests pass (1073 across 22 test binaries, plus 20 doc-tests)
cd crates/capi && cargo test exit 0 — 102 passed

This is not a stale-checkout or wrong-Python problem: CI is green on the same commit, and the workspace-root run still segfaults with python3 at 3.14.6.

thread 'abstract_::iter::tests::next_item' panicked at
  pyo3-ffi-0.29.0/src/cpython/listobject.rs:33:5: null pointer dereference occurred
thread caused non-unwinding panic. aborting.

Which test dies varies with thread scheduling — whichever list-touching test runs first.

Why

crates/capi/.cargo/config.toml sets PYO3_CONFIG_FILE to pyo3-rustpython.config, which declares implementation=RustPython. pyo3 emits cargo:rustc-cfg=RustPython for that, which compiles out the struct-poking fast paths:

// pyo3-ffi/src/lib.rs
#[cfg(not(any(Py_LIMITED_API, RustPython)))]
mod cpython;

But per the Cargo Book, "when invoked from a workspace root, Cargo does not read config files from crates within the workspace." So from the root that config is skipped, mod cpython is compiled, and PyList::new dereferences PyListObject.ob_item on a RustPython object.

CI sidesteps this in two places — --exclude rustpython-capi on the workspace run, and working-directory: crates/capi on the separate c-api step. CONTRIBUTING.md does neither, and it is the first command a new contributor runs.

Possible fixes

  1. Update CONTRIBUTING.md to mirror CI — add --exclude rustpython-capi and document the separate cd crates/capi && cargo test step.
  2. Give crates/capi its own [workspace], or set root default-members, so --workspace never picks it up and the documented command works unchanged.
  3. Something else that makes the root invocation safe.

Drafted with AI assistance (Claude Code) and reviewed by me before posting.

Metadata

Metadata

Assignees

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