Skip to content

Commit 6db20ca

Browse files
authored
Fix undefined array key in DeduplicationHandler with concurrent access (#2020)
When multiple requests write to the deduplication store file simultaneously, partially written lines can be read by concurrent processes. This causes 'Undefined array key' errors when trying to destructure incomplete lines. Changes: - Skip incomplete/invalid lines in isDuplicate() instead of crashing - Add LOCK_EX flag to file_put_contents() for atomic writes Fixes #1950
1 parent 922bace commit 6db20ca

1 file changed

Lines changed: 9 additions & 2 deletions

File tree

src/Monolog/Handler/DeduplicationHandler.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ public function flush(): void
8282
$passthru = $passthru === true || !\is_array($store) || !$this->isDuplicate($store, $record);
8383
if ($passthru) {
8484
$line = $this->buildDeduplicationStoreEntry($record);
85-
file_put_contents($this->deduplicationStore, $line . "\n", FILE_APPEND);
85+
file_put_contents($this->deduplicationStore, $line . "\n", FILE_APPEND | LOCK_EX);
8686
if (!\is_array($store)) {
8787
$store = [];
8888
}
@@ -114,7 +114,14 @@ protected function isDuplicate(array $store, LogRecord $record): bool
114114
$yesterday = time() - 86400;
115115

116116
for ($i = \count($store) - 1; $i >= 0; $i--) {
117-
list($timestamp, $level, $message) = explode(':', $store[$i], 3);
117+
$parts = explode(':', $store[$i], 3);
118+
119+
if (\count($parts) < 3) {
120+
// Skip invalid/incomplete lines (e.g. partially written due to concurrent access)
121+
continue;
122+
}
123+
124+
[$timestamp, $level, $message] = $parts;
118125

119126
if ($level === $record->level->getName() && $message === $expectedMessage && $timestamp > $timestampValidity) {
120127
return true;

0 commit comments

Comments
 (0)