mirror of
https://github.com/openai/codex.git
synced 2026-10-21 17:48:44 +00:00
## Why Concurrent TLS client builds can independently load the same platform trust store. Share overlapping loads while preserving fresh trust reads for later builds. ## What changed - Share one in-flight native root load without reusing completed loads. - Bypass sharing when `SSL_CERT_FILE` or `SSL_CERT_DIR` is set, and continue reading custom CA bundles independently for every build. ## Testing Add tests for overlapping loads, fresh trust after completion, and recovery from a panicking loader. Extend TLS handshake coverage to verify that replacing a custom CA file affects new configurations while existing configurations retain their trust, and that empty or removed files produce errors. GitOrigin-RevId: 1465ef3faf82f53651d9dbfe314341b17346580b
56 lines
2.1 KiB
Rust
56 lines
2.1 KiB
Rust
//! Verifies overlapping root loads, fresh trust generations, and panic recovery.
|
|
|
|
use super::*;
|
|
use pretty_assertions::assert_eq;
|
|
use rustls_pki_types::CertificateDer;
|
|
use rustls_pki_types::pem::PemObject;
|
|
use std::sync::mpsc;
|
|
use std::thread;
|
|
|
|
#[test]
|
|
fn concurrent_loads_share_roots_but_completed_loads_are_never_reused() {
|
|
let loader = NativeRootsLoader::default();
|
|
let (entered, started) = mpsc::channel();
|
|
let (release, released) = mpsc::channel();
|
|
thread::scope(|scope| {
|
|
let first_loader = &loader;
|
|
let first = scope.spawn(move || {
|
|
first_loader.load(|| {
|
|
entered.send(()).unwrap();
|
|
released.recv().unwrap();
|
|
RootCertStore::empty()
|
|
})
|
|
});
|
|
started.recv().unwrap();
|
|
let pending = loader.in_flight.lock().unwrap().upgrade().unwrap();
|
|
let second = scope.spawn(|| loader.load(|| panic!("overlapping load must be shared")));
|
|
// Wait for the second caller to own this generation before allowing it to finish.
|
|
while Arc::strong_count(&pending) < 3 {
|
|
thread::yield_now();
|
|
}
|
|
drop(loader.in_flight.lock().unwrap());
|
|
release.send(()).unwrap();
|
|
let first = first.join().unwrap();
|
|
let second = second.join().unwrap();
|
|
assert!(Arc::ptr_eq(&first, &second));
|
|
|
|
// Keep the old generation alive: completion, not refcount expiry, must force a reload.
|
|
let updated = loader.load(|| {
|
|
let mut roots = RootCertStore::empty();
|
|
roots.add_parsable_certificates(
|
|
CertificateDer::pem_slice_iter(include_bytes!("../tests/fixtures/test-ca.pem"))
|
|
.map(Result::unwrap),
|
|
);
|
|
roots
|
|
});
|
|
assert_eq!((first.len(), second.len(), updated.len()), (0, 0, 1));
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn panicking_load_does_not_poison_later_trust_reads() {
|
|
let loader = NativeRootsLoader::default();
|
|
assert!(std::panic::catch_unwind(|| loader.load(|| panic!("interrupted load"))).is_err());
|
|
assert!(loader.load(RootCertStore::empty).is_empty());
|
|
}
|