Skip to main content

windows_overlapped_io_sys/
config.rs

1// Copyright (c) 2026 Mike Grier
2//! Process-wide diagnostic configuration.
3//!
4//! Per-operation source tracking records where each operation was submitted so
5//! the drop-time rundown diagnostic can name the sources of any operation still
6//! outstanding. It is off by default because, when on, it takes a mutex on the
7//! submission hot path. Rundown correctness never depends on it.
8
9use std::sync::OnceLock;
10
11/// The name of the environment variable that provides the default setting.
12const ENV_VAR: &str = "WINDOWS_OVERLAPPED_IO_SYS_TRACK";
13
14static SOURCE_TRACKING: OnceLock<bool> = OnceLock::new();
15
16/// Returned when source tracking is configured after it has already been set.
17#[derive(Debug)]
18pub struct SourceTrackingAlreadySet;
19
20impl std::fmt::Display for SourceTrackingAlreadySet {
21    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22        f.write_str("operation source tracking was already configured")
23    }
24}
25
26impl std::error::Error for SourceTrackingAlreadySet {}
27
28/// Enable or disable per-operation source tracking for the whole process.
29///
30/// This is a one-time in-process setting: it must be called before the first
31/// operation is submitted and before any call to [`source_tracking_enabled`], or
32/// it returns [`SourceTrackingAlreadySet`]. When it is never called, the setting
33/// defaults from the `WINDOWS_OVERLAPPED_IO_SYS_TRACK` environment variable,
34/// which enables tracking when set to `1`, `true`, `on`, or `yes`.
35///
36/// # Errors
37///
38/// Returns [`SourceTrackingAlreadySet`] if the setting has already been resolved.
39pub fn set_source_tracking(enabled: bool) -> Result<(), SourceTrackingAlreadySet> {
40    SOURCE_TRACKING
41        .set(enabled)
42        .map_err(|_| SourceTrackingAlreadySet)
43}
44
45/// Whether per-operation source tracking is enabled for this process.
46///
47/// The first call resolves the setting from the environment if it was not set
48/// explicitly, and the result is then fixed for the rest of the process.
49#[must_use]
50pub fn source_tracking_enabled() -> bool {
51    *SOURCE_TRACKING.get_or_init(default_from_env)
52}
53
54fn default_from_env() -> bool {
55    match std::env::var(ENV_VAR) {
56        Ok(value) => matches!(
57            value.trim().to_ascii_lowercase().as_str(),
58            "1" | "true" | "on" | "yes"
59        ),
60        Err(_) => false,
61    }
62}