|
13 | 13 | StateSetMetricFamily, Summary, SummaryMetricFamily, UntypedMetricFamily, |
14 | 14 | ) |
15 | 15 | from prometheus_client.decorator import getargspec |
| 16 | +from prometheus_client.errors import PrometheusClientRuntimeError |
16 | 17 | from prometheus_client.metrics import _get_use_created |
17 | 18 | from prometheus_client.validation import ( |
18 | 19 | disable_legacy_validation, enable_legacy_validation, |
@@ -134,6 +135,19 @@ def test_exemplar_too_long(self): |
134 | 135 | 'y123456': '7+15 characters', |
135 | 136 | }) |
136 | 137 |
|
| 138 | + def test_single_thread_deadlock_detection(self): |
| 139 | + counter = self.counter |
| 140 | + |
| 141 | + class Tracked(float): |
| 142 | + def __radd__(self, other): |
| 143 | + counter.inc(10) |
| 144 | + return self + other |
| 145 | + |
| 146 | + expected_msg = 'Attempt to enter a non reentrant context from a single thread.' |
| 147 | + self.assertRaisesRegex( |
| 148 | + PrometheusClientRuntimeError, expected_msg, counter.inc, Tracked(100) |
| 149 | + ) |
| 150 | + |
137 | 151 |
|
138 | 152 | class TestDisableCreated(unittest.TestCase): |
139 | 153 | def setUp(self): |
@@ -1004,7 +1018,20 @@ def test_restricted_registry_does_not_yield_while_locked(self): |
1004 | 1018 | m = Metric('target', 'Target metadata', 'info') |
1005 | 1019 | m.samples = [Sample('target_info', {'foo': 'bar'}, 1)] |
1006 | 1020 | for _ in registry.restricted_registry(['target_info', 's_sum']).collect(): |
1007 | | - self.assertFalse(registry._lock.locked()) |
| 1021 | + self.assertFalse(registry._lock._locked()) |
| 1022 | + |
| 1023 | + def test_registry_deadlock_detection(self): |
| 1024 | + registry = CollectorRegistry(auto_describe=True) |
| 1025 | + |
| 1026 | + class RecursiveCollector: |
| 1027 | + def collect(self): |
| 1028 | + Counter('x', 'help', registry=registry) |
| 1029 | + return [CounterMetricFamily('c_total', 'help', value=1)] |
| 1030 | + |
| 1031 | + expected_msg = 'Attempt to enter a non reentrant context from a single thread.' |
| 1032 | + self.assertRaisesRegex( |
| 1033 | + PrometheusClientRuntimeError, expected_msg, registry.register, RecursiveCollector() |
| 1034 | + ) |
1008 | 1035 |
|
1009 | 1036 |
|
1010 | 1037 | if __name__ == '__main__': |
|
0 commit comments