Skip to content

Commit a09ea80

Browse files
Avoid possible infinite loops on APCu eviction (#136)
If we are unlucky with an APCu eviction at the wrong moment, and no other thread writing to the same metric, we can get stuck in an infinite loop where apcu_fetch will always return false. Fix by applying the same strategy as if apcu_fetch was false in the first place (before doing compare-and-swap) Signed-off-by: Tobias Bengtsson <me@tobiasbengtsson.se> Co-authored-by: Lukas Kämmerling <lukas.kaemmerling@hetzner-cloud.de>
1 parent 3f915df commit a09ea80

File tree

1 file changed

+15
-0
lines changed

1 file changed

+15
-0
lines changed

src/Prometheus/Storage/APC.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,13 @@ public function updateHistogram(array $data): void
7272
$old = apcu_fetch($sumKey);
7373
if ($old !== false) {
7474
$done = apcu_cas($sumKey, $old, $this->toBinaryRepresentationAsInteger($this->fromBinaryRepresentationAsInteger($old) + $data['value']));
75+
} else {
76+
$new = apcu_add($sumKey, $this->toBinaryRepresentationAsInteger(0));
77+
78+
// If sum does not exist, assume a new histogram and store the metadata
79+
if ($new) {
80+
apcu_store($this->metaKey($data), json_encode($this->metaData($data)));
81+
}
7582
}
7683
}
7784

@@ -160,6 +167,11 @@ public function updateGauge(array $data): void
160167
$old = apcu_fetch($valueKey);
161168
if ($old !== false) {
162169
$done = apcu_cas($valueKey, $old, $this->toBinaryRepresentationAsInteger($this->fromBinaryRepresentationAsInteger($old) + $data['value']));
170+
} else {
171+
$new = apcu_add($valueKey, $this->toBinaryRepresentationAsInteger(0));
172+
if ($new) {
173+
apcu_store($this->metaKey($data), json_encode($this->metaData($data)));
174+
}
163175
}
164176
}
165177
}
@@ -183,6 +195,9 @@ public function updateCounter(array $data): void
183195
$old = apcu_fetch($valueKey);
184196
if ($old !== false) {
185197
$done = apcu_cas($valueKey, $old, $this->toBinaryRepresentationAsInteger($this->fromBinaryRepresentationAsInteger($old) + $data['value']));
198+
} else {
199+
apcu_add($this->valueKey($data), 0);
200+
apcu_store($this->metaKey($data), json_encode($this->metaData($data)));
186201
}
187202
}
188203
}

0 commit comments

Comments
 (0)