Skip to content

ban_raw_subprocess dylint: enforce wrapper for all subprocess spawns #264

@zackees

Description

@zackees

Follow-up to #261 / PR #262.

Goal

Land the custom ban_raw_subprocess dylint that forbids direct std::process::Command::{spawn,output,status} and tokio::process::Command::{spawn,output,status} outside an allowlist, so all subprocess spawns are forced through fbuild_core::subprocess::run_command (NativeProcess wrapper) or fbuild_core::containment::{spawn_contained, spawn_detached, tokio_spawn::spawn_contained} (containment wrappers).

This was prototyped in #262 (commit 634e9e5) and reverted before merge.

Why it was deferred

PR #262 attempted to land the dylint alongside the LTO fix, but ran into three CR blockers:

  1. CI integration is non-trivial. Published dylint_driver 5.0.0 doesnt build against the nightly-2026-03-26 toolchain that dylint_linting 5.0.0 wants. zccache solves this with ci/build_dylint_driver.py which clones dylints git rev and builds a matching driver. fbuild needs the same script (or to find a published combo that works without it).

  2. Scope filter too loose. SOURCE_PREFIX = "crates/" matched crates/*/tests/, crates/*/examples/, crates/*/benches/ etc. Either tighten to crates/*/src/ or broaden the allowlist to cover all test/example/bench files using Command::* directly.

  3. Missing qpath handling. The check_expr arm only handles ExprKind::MethodCall. Qualified-path calls (<Command>::spawn(&mut cmd), tokio::process::Command::spawn(&mut cmd)) also need to be caught via ExprKind::Call + qpath_res.

Acceptance criteria

  • Port ci/build_dylint_driver.py from zccache so CI can run cargo dylint --all.
  • Tighten or broaden the source-file scope per (2); allowlist any remaining legitimate raw-spawn test files.
  • Extend the lint to handle ExprKind::Call qualified-path syntax (mirror zccache's pattern for both call shapes).
  • CI step on check-ubuntu.yml runs the dylint with -D warnings and passes.

Reference

  • zccache pattern: ~/dev/zccache/dylints/ban_raw_subprocess_in_daemon/, ci/build_dylint_driver.py, .github/workflows/ci.yml::dylint job.
  • Prototype on the reverted PR fix(linker): redirect GCC LTO temp dir (#261) #262 commit 634e9e5: dylints/ban_raw_subprocess/{Cargo.toml,Cargo.lock,README.md,rust-toolchain.toml,src/lib.rs,src/allowlist.txt}.

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions