From 290369f3830176b3359c4ed8376ecd0e48c192dd Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Thu, 13 Oct 2022 10:37:05 +0200 Subject: [PATCH] Fix Family::get_or_create The method should not overwrite an existing key after it obtains the write lock. Consider the following scenario with `Family` used by threads A and B: 1. A and B both call `family.get_or_insert(&label_set)` 2. A and B both acquire read lock and finds no key 3. A gets write lock and inserts a new gauge with value 0 4. A increments returned gauge to 1 5. B gets write lock and inserts a new gauge with value 0 6. B increments returned gauge to 1 7. A decrements gauge back to 0 8. B decrements gauge which now overflows to `u64::MAX` Signed-off-by: Anthony Ramine --- CHANGELOG.md | 5 +++++ src/metrics/family.rs | 11 +++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0532a102..45469111 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,9 +18,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Move`Encode` trait from `prometheus_client::encoding::text` to `prometheus_client::encoding`. See [PR 83]. +### Fixed + +- Fix race condition in `Family::get_or_create`. See [PR 102]. + [PR 83]: https://github.com/prometheus/client_rust/pull/83 [PR 85]: https://github.com/prometheus/client_rust/pull/85 [PR 96]: https://github.com/prometheus/client_rust/pull/96 +[PR 102]: https://github.com/prometheus/client_rust/pull/102 ## [0.18.0] diff --git a/src/metrics/family.rs b/src/metrics/family.rs index c3cf6b9b..bb163761 100644 --- a/src/metrics/family.rs +++ b/src/metrics/family.rs @@ -3,7 +3,7 @@ //! See [`Family`] for details. use super::{MetricType, TypedMetric}; -use parking_lot::{MappedRwLockReadGuard, RwLock, RwLockReadGuard}; +use parking_lot::{MappedRwLockReadGuard, RwLock, RwLockReadGuard, RwLockWriteGuard}; use std::collections::HashMap; use std::sync::Arc; @@ -223,11 +223,14 @@ impl> Family