Skip to content

Commit 591e91f

Browse files
suligapcsmarchbanks
authored andcommitted
Drop incorrect use of reentrant locks (#1076)
This fixes a correctness bug introduced in 0014e97 resulting in lost updates during some scenarios. The code being locked is not reentrant safe. It's preferable to deadlock in these situations instead of silently loosing updates for example. Signed-off-by: Przemysław Suliga <[email protected]>
1 parent 3b183b4 commit 591e91f

File tree

4 files changed

+10
-18
lines changed

4 files changed

+10
-18
lines changed

prometheus_client/metrics.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import os
2-
from threading import RLock
2+
from threading import Lock
33
import time
44
import types
55
from typing import (
@@ -144,7 +144,7 @@ def __init__(self: T,
144144

145145
if self._is_parent():
146146
# Prepare the fields needed for child metrics.
147-
self._lock = RLock()
147+
self._lock = Lock()
148148
self._metrics: Dict[Sequence[str], T] = {}
149149

150150
if self._is_observable():
@@ -697,7 +697,7 @@ class Info(MetricWrapperBase):
697697

698698
def _metric_init(self):
699699
self._labelname_set = set(self._labelnames)
700-
self._lock = RLock()
700+
self._lock = Lock()
701701
self._value = {}
702702

703703
def info(self, val: Dict[str, str]) -> None:
@@ -759,7 +759,7 @@ def __init__(self,
759759

760760
def _metric_init(self) -> None:
761761
self._value = 0
762-
self._lock = RLock()
762+
self._lock = Lock()
763763

764764
def state(self, state: str) -> None:
765765
"""Set enum metric state."""

prometheus_client/registry.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from abc import ABC, abstractmethod
22
import copy
3-
from threading import RLock
3+
from threading import Lock
44
from typing import Dict, Iterable, List, Optional
55

66
from .metrics_core import Metric
@@ -30,7 +30,7 @@ def __init__(self, auto_describe: bool = False, target_info: Optional[Dict[str,
3030
self._collector_to_names: Dict[Collector, List[str]] = {}
3131
self._names_to_collectors: Dict[str, Collector] = {}
3232
self._auto_describe = auto_describe
33-
self._lock = RLock()
33+
self._lock = Lock()
3434
self._target_info: Optional[Dict[str, str]] = {}
3535
self.set_target_info(target_info)
3636

prometheus_client/values.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import os
2-
from threading import RLock
2+
from threading import Lock
33
import warnings
44

55
from .mmap_dict import mmap_key, MmapedDict
@@ -13,7 +13,7 @@ class MutexValue:
1313
def __init__(self, typ, metric_name, name, labelnames, labelvalues, help_text, **kwargs):
1414
self._value = 0.0
1515
self._exemplar = None
16-
self._lock = RLock()
16+
self._lock = Lock()
1717

1818
def inc(self, amount):
1919
with self._lock:
@@ -50,7 +50,7 @@ def MultiProcessValue(process_identifier=os.getpid):
5050
# Use a single global lock when in multi-processing mode
5151
# as we presume this means there is no threading going on.
5252
# This avoids the need to also have mutexes in __MmapDict.
53-
lock = RLock()
53+
lock = Lock()
5454

5555
class MmapedValue:
5656
"""A float protected by a mutex backed by a per-process mmaped file."""

tests/test_core.py

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,6 @@
1616
from prometheus_client.metrics import _get_use_created
1717

1818

19-
def is_locked(lock):
20-
"Tries to obtain a lock, returns True on success, False on failure."
21-
locked = lock.acquire(blocking=False)
22-
if locked:
23-
lock.release()
24-
return not locked
25-
26-
2719
def assert_not_observable(fn, *args, **kwargs):
2820
"""
2921
Assert that a function call falls with a ValueError exception containing
@@ -971,7 +963,7 @@ def test_restricted_registry_does_not_yield_while_locked(self):
971963
m = Metric('target', 'Target metadata', 'info')
972964
m.samples = [Sample('target_info', {'foo': 'bar'}, 1)]
973965
for _ in registry.restricted_registry(['target_info', 's_sum']).collect():
974-
self.assertFalse(is_locked(registry._lock))
966+
self.assertFalse(registry._lock.locked())
975967

976968

977969
if __name__ == '__main__':

0 commit comments

Comments
 (0)