mirror of
https://github.com/openai/codex.git
synced 2026-11-12 22:42:36 +00:00
Keep the latest Guardian risk score during concurrent sampling (#38580)
## Why Concurrent Guardian samples can finish out of order, allowing an older sample to replace the thread's newer in-memory security risk score. ## What changed - Record when each `SecurityRiskScore` sample starts while preserving compatibility with records that have no timestamp. - Add `ExtensionData::insert_if` so checking and replacing a typed attachment happen under the same lock. - Update Guardian V2 to replace the thread's risk score only when the completed sample is newer than the stored one. ## Testing - Verify concurrent conditional inserts retain the newest value. - Verify Guardian-generated risk scores include a sampling timestamp. GitOrigin-RevId: 6543a4e5497da4c623331050789e91613f931c4b
This commit is contained in:
1 parent
42d842a91a
commit
2a452d7dc1
11 files changed
+76
-2
No files matched your search
@@ -1,5 +1,6 @@
|
||||
use std::panic::AssertUnwindSafe;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Barrier;
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
@@ -29,6 +30,36 @@ fn typed_values_can_be_inserted_replaced_and_removed() {
|
||||
assert_eq!(data.get::<u64>().as_deref(), Some(&42));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn conditional_insert_keeps_the_newest_concurrent_value() {
|
||||
const CALLER_COUNT: u64 = 16;
|
||||
|
||||
let data = Arc::new(ExtensionData::new("thread-1"));
|
||||
let callers_ready = Arc::new(Barrier::new(CALLER_COUNT as usize));
|
||||
let handles = (0..CALLER_COUNT)
|
||||
.map(|value| {
|
||||
let data = Arc::clone(&data);
|
||||
let callers_ready = Arc::clone(&callers_ready);
|
||||
std::thread::spawn(move || {
|
||||
callers_ready.wait();
|
||||
data.insert_if(value, |existing| {
|
||||
existing.is_none_or(|existing| value > *existing)
|
||||
});
|
||||
})
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
for handle in handles {
|
||||
handle.join().expect("insertion thread should succeed");
|
||||
}
|
||||
|
||||
assert_eq!(data.get::<u64>().as_deref(), Some(&(CALLER_COUNT - 1)));
|
||||
assert!(!data.insert_if(/*value*/ 0_u64, |existing| {
|
||||
existing.is_none_or(|existing| *existing == 0)
|
||||
}));
|
||||
assert_eq!(data.get::<u64>().as_deref(), Some(&(CALLER_COUNT - 1)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_or_init_initializes_once_and_returns_shared_value() {
|
||||
const CALLER_COUNT: usize = 8;
|
||||
|
||||
Reference in new issue
Block a user