mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-10 07:06:53 +00:00
422e0ad768
rename_all_missing_source_still_warns and rename_all_real_failure_still_warns
assert that `warn_reliable_rename_failure` emitted its WARN, but that is a
single production callsite shared with tests that call rename_all *without*
installing a subscriber — rename_all_missing_source_returns_file_not_found,
two tests above, is one of them.
tracing caches each callsite's Interest process-globally and the first thread
to reach a callsite fixes that value; while at most one dispatcher is
registered, tracing-core derives it from the registering thread's own
subscriber, and registration is once-only. When the subscriber-less sibling
wins, the callsite is cached as Interest::never() and the WARN never fires,
so the assertion sees empty output:
ordinary missing-source failures must keep the WARN, got:
Reproduced at 3/25 with `disk::os::tests::rename_all_missing_source` (both
tests), against 0/20 for the victim alone. Fixed by pinning callsite interest
inside warn_capture(), so every current and future user of that helper is
covered rather than just the two tests that happen to fail today.
pin_callsite_interest_for_test() moves from cluster::rpc::background_monitor
to a new crate-level test_tracing module: it is domain-neutral and now has
consumers in two unrelated subsystems, and disk::os should not have to reach
into a cluster::rpc test helper.
Verified: repro filter 0/30 (was 3/25); disk::os:: 0/12; cluster::rpc:: 0/12
and its poisoner pair 0/15, confirming the moved helper still holds.
Follow-up to #5438. Closes the last item in #5439.
44 lines
2.5 KiB
Rust
44 lines
2.5 KiB
Rust
//! Test-only guard against tracing's process-global callsite-interest cache.
|
|
//!
|
|
//! Any test that installs its own subscriber and then asserts on span or event
|
|
//! context is asserting on process-global state. See
|
|
//! [`pin_callsite_interest_for_test`] for what goes wrong and why holding its
|
|
//! guard fixes it.
|
|
|
|
/// Stop a sibling test thread from poisoning tracing's process-global callsite
|
|
/// interest cache while this test asserts on span or event context.
|
|
///
|
|
/// `tracing` caches every callsite's `Interest` in **process-global** state, and
|
|
/// the first thread to reach a callsite fixes that value. While at most one
|
|
/// dispatcher is registered, tracing-core takes a fast path
|
|
/// (`Dispatchers::rebuilder` -> `Rebuilder::JustOne`) that derives a
|
|
/// newly-registered callsite's interest from whichever subscriber is current
|
|
/// *on the registering thread*, and registration happens exactly once (guarded
|
|
/// by a CAS in `DefaultCallsite::register`).
|
|
///
|
|
/// In a multi-threaded `cargo test` binary a sibling test therefore routinely
|
|
/// reaches a production callsite first, from a thread with no subscriber
|
|
/// installed: the interest is derived from that thread's `NoSubscriber` and
|
|
/// cached as `Interest::never()` for the whole process. From then on the
|
|
/// callsite is dead for *every* later caller, including a test that installed
|
|
/// its own subscriber — an `info_span!` silently evaluates to `Span::none()`, and
|
|
/// a `warn!`/`info!` event never fires at all.
|
|
///
|
|
/// Registering a second, inert dispatcher closes both halves of that race:
|
|
///
|
|
/// * constructing it rebuilds every *already-registered* callsite's interest
|
|
/// against the live dispatcher set — which includes the caller's subscriber —
|
|
/// repairing whatever a sibling may already have poisoned; and
|
|
/// * holding it alive keeps tracing-core off the single-dispatcher fast path, so
|
|
/// a callsite registered *later* by any thread is resolved against that live
|
|
/// set instead of the registering thread's `NoSubscriber`.
|
|
///
|
|
/// Call this **after** installing the test's subscriber, and hold the returned
|
|
/// guard for the rest of the test. Only the `cargo test` fallback needs it:
|
|
/// nextest runs each test in its own process, where there is no sibling thread
|
|
/// to lose the race to (see `docs/testing/README.md`).
|
|
#[must_use = "callsite interest is only pinned while the returned guard is held"]
|
|
pub(crate) fn pin_callsite_interest_for_test() -> tracing::Dispatch {
|
|
tracing::Dispatch::new(tracing_core::subscriber::NoSubscriber::default())
|
|
}
|