Skip to content

Commit 00f21e9

Browse files
authored
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 <mail@suligap.net>
1 parent 33e6828 commit 00f21e9

File tree

4 files changed

+10
-18
lines changed

4 files changed

+10
-18
lines changed

prometheus_client/metrics.py

+4-4
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 (
@@ -120,7 +120,7 @@ def __init__(self: T,
120120

121121
if self._is_parent():
122122
# Prepare the fields needed for child metrics.
123-
self._lock = RLock()
123+
self._lock = Lock()
124124
self._metrics: Dict[Sequence[str], T] = {}
125125

126126
if self._is_observable():
@@ -673,7 +673,7 @@ class Info(MetricWrapperBase):
673673

674674
def _metric_init(self):
675675
self._labelname_set = set(self._labelnames)
676-
self._lock = RLock()
676+
self._lock = Lock()
677677
self._value = {}
678678

679679
def info(self, val: Dict[str, str]) -> None:
@@ -735,7 +735,7 @@ def __init__(self,
735735

736736
def _metric_init(self) -> None:
737737
self._value = 0
738-
self._lock = RLock()
738+
self._lock = Lock()
739739

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

prometheus_client/registry.py

+2-2
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

+3-3
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

+1-9
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,6 @@
1919
)
2020

2121

22-
def is_locked(lock):
23-
"Tries to obtain a lock, returns True on success, False on failure."
24-
locked = lock.acquire(blocking=False)
25-
if locked:
26-
lock.release()
27-
return not locked
28-
29-
3022
def assert_not_observable(fn, *args, **kwargs):
3123
"""
3224
Assert that a function call falls with a ValueError exception containing
@@ -1012,7 +1004,7 @@ def test_restricted_registry_does_not_yield_while_locked(self):
10121004
m = Metric('target', 'Target metadata', 'info')
10131005
m.samples = [Sample('target_info', {'foo': 'bar'}, 1)]
10141006
for _ in registry.restricted_registry(['target_info', 's_sum']).collect():
1015-
self.assertFalse(is_locked(registry._lock))
1007+
self.assertFalse(registry._lock.locked())
10161008

10171009

10181010
if __name__ == '__main__':

0 commit comments

Comments
 (0)