Skip to main content

Module trace

Module trace 

Source
Expand description

A trace for defects that only appear under concurrency, compiled out unless the trace feature is on and narrowed by environment variable when it is. See the module documentation for why an eprintln! is the wrong instrument for that class of problem.

Gated on Windows like every other Win32-backed module here: the traced build calls GetCurrentThreadId, so leaving it ungated would let --features trace break this crate’s empty-on-other-targets behaviour. A trace that is cheap enough to use on a timing-sensitive defect.

§Why this is not eprintln!

It exists for one class of problem: a fault that only appears under concurrency, where the obvious instrument destroys the thing it is measuring. Formatting and writing a line takes microseconds and a lock on stderr; the window being investigated may be shorter than that, so an eprintln! in the wrong place does not observe a race, it prevents one.

Three properties follow, and each is a deliberate cost:

  1. It compiles to nothing unless the trace feature is on. Every entry point below is #[inline(always)] and has an empty body without the feature, so a published build carries no branch, no atomic, and no storage. This is what makes it safe to leave the call sites in place.
  2. Recording does not format and does not allocate. An entry is a timestamp, a thread id, two &'static str labels and two u64 slots. Text is produced only when a dump is asked for, which happens after the interesting moment has passed.
  3. It is off at runtime even when compiled in, and when on it is narrowed rather than global – see crate::trace::enabled. A trace that records everything is a trace that changes the schedule of everything.

§Narrowing to one scenario

Set WINDOWS_THREADPOOL_TRACE to a comma-separated list of target substrings. Only records whose target contains one of them are kept:

$env:WINDOWS_THREADPOOL_TRACE = 'wait'            # just the wait object
$env:WINDOWS_THREADPOOL_TRACE = 'wait,delivery'   # two subsystems
$env:WINDOWS_THREADPOOL_TRACE = '*'               # everything

The targets this crate records under are wait, work, io, timer and timer-periodic – one per pool object – plus heal for the self-heal registry, syscall-enter and syscall-leave for the bracketed Win32 calls themselves, and exception when exception observation is switched on. Targets are matched by substring, so timer selects the periodic timer as well. Dependent crates add their own; windows-ioring-sys records under delivery and, from its own tests, postmortem.

Unset, empty, or matching nothing means no record is kept and the cost is one relaxed atomic load per call site.

Functions§

clear
Does nothing in this build.
dump
Reports that the build carries no trace, which is a different finding from a build that traced and saw nothing.
enabled
Always false in this build: the feature is off.
observe_exceptions
Does nothing in this build: there is no trace to attribute exceptions to, so no handler is installed.
record
Does nothing in this build, and is expected to compile away entirely.
wants
Always false in this build: the feature is off.