Expand description
Process-wide cache for the system trust store.
rustls_native_certs::load_native_certs reaches into the OS
keychain (Security framework on macOS, NSS / OpenSSL stores on
Linux). On macOS the underlying Sec* APIs are not concurrency-safe
under load — multiple threads calling them in parallel can return
errSecIO (-36) on what would otherwise succeed. Production
daemons that build many distinct rustls ClientConfigs (one per
upstream-TLS fingerprint, e.g.) hit this whenever a reload
introduces a handful of new fingerprints concurrently.
The fix is a process-wide cache: read the trust store once per
process, share the resulting rustls::RootCertStore behind
Arc. The std::sync::OnceLock initializer barrier serialises
the (single) load attempt; every subsequent caller gets a cheap
Arc::clone.
In-process the OnceLock is sufficient. Across processes (e.g. a
test runner that boots multiple binaries in parallel) each binary
still makes its own first call, and those simultaneous calls can
lose to keychain contention. The init path therefore retries on
transient failure with a small backoff before giving up —
errSecIO is documented by Apple as recoverable, and the happy
path skips the backoff entirely.
Failure semantics: after the bounded retries are exhausted the outcome is sticky. The cached error re-yields on every subsequent call so the operator sees consistent behaviour and can restart the process to attempt a fresh load — there is no per-request retry storm against an OS API that is already telling us it is unhappy.
Structs§
- Native
Roots Error - Shared error type. Carries an operator-readable message; the
underlying
rustls_native_certs::Erroris notClone, so we stringify at first-failure time and re-yield the same string on subsequent calls.
Functions§
- native_
roots - Return the cached system trust store, loading it on first call.
- warm_
native_ roots - Eagerly trigger the first load. Useful when a daemon’s boot path wants to know the trust-store status before any TLS code runs — idempotent; subsequent calls return the cached result without re-touching the OS keychain.