mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-31 17:28:12 +00:00
fix: harden io-core and concurrency boundaries against panics (#4503)
fix(io-core,concurrency): harden boundary validation and arithmetic against panics (backlog#1024)
This commit is contained in:
@@ -223,7 +223,18 @@ impl BackpressureMonitor {
|
||||
|
||||
/// Release a slot after operation completes.
|
||||
pub fn release(&self) {
|
||||
let prev = self.current.fetch_sub(1, Ordering::Relaxed);
|
||||
// Guard against underflow: an unpaired release at 0 must not wrap to
|
||||
// usize::MAX, which would permanently reject all future acquisitions.
|
||||
let prev = match self
|
||||
.current
|
||||
.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |current| current.checked_sub(1))
|
||||
{
|
||||
Ok(prev) => prev,
|
||||
Err(_) => {
|
||||
tracing::warn!("BackpressureMonitor::release called with no outstanding acquisition; ignoring");
|
||||
0
|
||||
}
|
||||
};
|
||||
let low_threshold = self.config.low_threshold();
|
||||
|
||||
// Update state if needed
|
||||
@@ -362,6 +373,22 @@ mod tests {
|
||||
assert_eq!(monitor.state(), BackpressureState::Normal);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_release_underflow_stays_at_zero() {
|
||||
// An unpaired release at current==0 must not wrap to usize::MAX,
|
||||
// which would make try_acquire reject everything forever.
|
||||
let monitor = BackpressureMonitor::with_defaults();
|
||||
|
||||
monitor.release();
|
||||
assert_eq!(monitor.current(), 0);
|
||||
|
||||
// The monitor must still be usable.
|
||||
assert!(monitor.try_acquire());
|
||||
assert_eq!(monitor.current(), 1);
|
||||
monitor.release();
|
||||
assert_eq!(monitor.current(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rejection_rate() {
|
||||
let config = BackpressureConfig {
|
||||
|
||||
Reference in New Issue
Block a user