Skip to content

fix(tracing): flush guards on Ctrl-C and doctor-subcommand exit - #6697

Merged
bug-ops merged 1 commit into
mainfrom
fix/6696-ctrlc-guard-flush-bypass
Jul 28, 2026
Merged

fix(tracing): flush guards on Ctrl-C and doctor-subcommand exit#6697
bug-ops merged 1 commit into
mainfrom
fix/6696-ctrlc-guard-flush-bypass

Conversation

@bug-ops

@bug-ops bug-ops commented Jul 28, 2026

Copy link
Copy Markdown
Owner

Summary

  • std::process::exit runs no destructors, so early_ctrlc's Ctrl-C handler and the Doctor/Gonka::Doctor/Cocoon::Doctor subcommand exits (src/runner.rs) bypassed TracingGuards::drop's take-once-cell flush logic entirely, truncating the log file and/or local Chrome trace on every early exit through those paths. Unlike the SIGTERM race window fixed in log_guard (rolling file WorkerGuard) has same SIGTERM-flush gap as chrome_guard had #6693, the Ctrl-C gap was a 100%-reproducible bypass on every platform.
  • Added exit_with_flush and flush_and_exit_on_ctrlc in src/tracing_init.rs, and extracted the previously-duplicated lock-hold-across-flush logic into a shared take_and_flush_guard_cells helper reused by TracingGuards::drop, spawn_sigterm_flush_task, and the new Ctrl-C path.
  • tokio::signal::ctrl_c() is cross-platform, so this also closes the non-Unix half of the gap that log_guard (rolling file WorkerGuard) has same SIGTERM-flush gap as chrome_guard had #6693 left open.

Closes #6696

Scope notes

Two sites sharing the same std::process::exit pattern (runner.rs:1186 Notify::Test, :1231 UrlScheme::Status) and 5 deep-link-feature-gated sites inside handle_url_open share the same bug class but were intentionally left out of scope — a follow-up issue will be filed for them.

Review chain

Test plan

  • cargo +nightly fmt --check
  • cargo clippy --profile ci --workspace --all-targets --features "desktop,ide,server,chat,pdf,scheduler,testing" -- -D warnings
  • cargo nextest run --config-file .github/nextest.toml --workspace --features "desktop,ide,server,chat,pdf,scheduler" --lib --bins (15258/15258 passed, including all tracing_init tests unmodified)
  • RUSTFLAGS="-D warnings" RUSTDOCFLAGS="--deny rustdoc::broken_intra_doc_links" cargo doc --no-deps --workspace --features "desktop,ide,server,chat,pdf,scheduler"
  • gitleaks protect --staged --no-banner --redact
  • No new automated test was added for exit_with_flush/flush_and_exit_on_ctrlc themselves — both call std::process::exit and are untestable in-process (verified no assert_cmd/subprocess-exit test harness precedent exists in the repo). take_and_flush_guard_cells is indirectly covered via existing TracingGuards::drop tests.

std::process::exit runs no destructors, so early_ctrlc's Ctrl-C handler
and the Doctor/Gonka::Doctor/Cocoon::Doctor subcommand exits bypassed
TracingGuards::drop's take-once-cell flush logic entirely, truncating
the log file and/or local Chrome trace on every early exit through
those paths. Unlike the SIGTERM race window fixed in #6693, the Ctrl-C
gap was a 100%-reproducible bypass on every platform.

Add exit_with_flush and flush_and_exit_on_ctrlc in tracing_init.rs,
and extract the previously-duplicated lock-hold-across-flush logic
into a shared take_and_flush_guard_cells helper reused by
TracingGuards::drop, spawn_sigterm_flush_task, and the new Ctrl-C
path. tokio::signal::ctrl_c() is cross-platform, so this also closes
the non-Unix half of the gap that #6693 left open.

Two sites sharing the same pattern (Notify::Test, UrlScheme::Status)
and 5 deep-link-feature-gated sites inside handle_url_open share the
same bug but are intentionally left out of scope for a follow-up.
@github-actions github-actions Bot added bug Something isn't working size/L Large PR (201-500 lines) documentation Improvements or additions to documentation labels Jul 28, 2026
@bug-ops
bug-ops enabled auto-merge (squash) July 28, 2026 15:30
@bug-ops
bug-ops merged commit ea0e8e9 into main Jul 28, 2026
43 checks passed
@bug-ops
bug-ops deleted the fix/6696-ctrlc-guard-flush-bypass branch July 28, 2026 15:39
bug-ops added a commit that referenced this pull request Jul 28, 2026
Notify::Test and UrlScheme::Status --check now call exit_with_flush
instead of a bare std::process::exit. handle_url_open (deep-link
feature) now returns Option<i32> instead of exiting internally,
since tracing_guards is not in scope inside that function; the
caller in run() flushes and exits on its behalf.

Follow-up from #6697, which fixed the same bug class at other sites
but left these 7 untouched.
bug-ops added a commit that referenced this pull request Jul 28, 2026
Notify::Test and UrlScheme::Status --check now call exit_with_flush
instead of a bare std::process::exit. handle_url_open (deep-link
feature) now returns Option<i32> instead of exiting internally,
since tracing_guards is not in scope inside that function; the
caller in run() flushes and exits on its behalf.

Follow-up from #6697, which fixed the same bug class at other sites
but left these 7 untouched.
bug-ops added a commit that referenced this pull request Jul 28, 2026
…t sites

std::process::exit skipped TracingGuards::drop's flush-on-drop logic at
every std::process::exit call site reachable from run() after
init_tracing, the same bug class as #6696/#6697/#6698/#6708. Rather than
threading exit-signal types through each site, unify on plain anyhow
Result propagation: load_config_or_default now returns
Result<Config, ConfigLoadError> instead of exiting internally, and every
caller (18 total, including the 7 exit sites in commands/bench.rs) uses
plain ? so an ordinary Err return unwinds and flushes tracing_guards via
normal drop.

Closes #6709
bug-ops added a commit that referenced this pull request Jul 28, 2026
…t sites (#6714)

std::process::exit skipped TracingGuards::drop's flush-on-drop logic at
every std::process::exit call site reachable from run() after
init_tracing, the same bug class as #6696/#6697/#6698/#6708. Rather than
threading exit-signal types through each site, unify on plain anyhow
Result propagation: load_config_or_default now returns
Result<Config, ConfigLoadError> instead of exiting internally, and every
caller (18 total, including the 7 exit sites in commands/bench.rs) uses
plain ? so an ordinary Err return unwinds and flushes tracing_guards via
normal drop.

Closes #6709
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working documentation Improvements or additions to documentation size/L Large PR (201-500 lines)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

early_ctrlc / doctor subcommands bypass guard-flush via process::exit, same root cause as #6693

1 participant