Repository navigation
The deadlock pattern only offers a report whose ERROR: is the line's own label, and the managed prefix's gap can't slide past the real pid (#4014) - #4042
Merged
Conversation
…own label, and the managed prefix's gap can't slide past the real pid (#4014) #4014 reported that a STATEMENT companion echoing "ERROR: deadlock detected" plus a tab-continued DETAIL matched the deadlock pattern through the line's real pid bracket. Measured end to end, the forgery never stores anything: since #4005 every candidate goes through PgLogEntryAssembler, whose label is the line's own. New tests pin that for the STATEMENT echo and for a forged header behind a real managed-prefix bracket. The pattern was still wider than the rule behind it, so both copies are narrowed to match it (defense in depth; fewer false candidates): - the gaps before ERROR: and before DETAIL: may not cross a field label's ": ", so the ERROR: matched is the line's first label; the %Q query id glued to the label still fits, pinned by the captured fixture; - the managed family's lazy gap to the pid bracket becomes [^\[\n]*, #4008's fix for plan capture, so it can't backtrack past the real bracket. Measured on PostgreSQL 18.6: the old SQL pattern offered the STATEMENT echo as a candidate; the new one offers only real reports. PgDeadlockCandidatePatternLiveTests runs the shipped pattern through PostgreSQL's regex engine and pins exactly that. Red-watched: with dev's pattern it fails (Expected 0, Actual 1). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GdmA4ND1wLSqA91ax1m4xv
erikdarlingdata
enabled auto-merge (squash)
September 23, 2026 13:43
This was referenced Sep 23, 2026
Closed
erikdarlingdata
added a commit
that referenced
this pull request
Sep 26, 2026
…4438) Adds the missing [Unreleased] CHANGELOG entries for nine merged PRs. Two more need none. - Fixed: #3588, #3886, #3889, #3900, #3911, #4016, #4032 and #4042. - Changed: #4157. llms.txt and CITATION.cff now match the shipped product. - None: - #4332 adds RawChunkIntervalPlanner without wiring it in; the later PR that wires it carries its own entry. - #4398 changes tests only. - Each entry was written from its PR's diff, with a [#N] label linking the pull request.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #4014.
Why
#4014 reported that a backend's STATEMENT companion echoing
ERROR: deadlock detected, with a tab-continuedDETAIL:, matched the deadlock pattern through the line's real pid bracket. That would attribute a forged deadlock to a real backend. The managed-prefix branch also kept the lazy[^\n]*?gap that #4008 removed from plan capture.Measured end to end, the forgery never stores anything. Since #4005 every candidate goes through
PgLogEntryAssembler(FromReport), whose label is the line's own, and it refuses both shapes. The new parser tests pin that. The pattern itself was still wider than that rule: on PostgreSQL 18.6, the old SQL pattern really did offer the STATEMENT echo as a candidate.What changes
The C# route (
PgDeadlockLogParser.s_deadlockBlock) and the self-hosted SQL route (PgDeadlocksCollector) change together, as defence in depth that matches the assembler's rule:ERROR:and beforeDETAIL:may not cross a field label's": ", so theERROR:matched is the line's first label. The%Qquery id glued to the label still fits, which the captured fixture pins. A prefix that itself renders": "(an application_name under%a) would hide that line's report; it can hide one, never forge one, and that's documented.[^\[\n]*, Plan capture reads a plan block anywhere in a log line, so a statement's author can attach a forged plan to any query id #4008's fix for plan capture, so it can't backtrack past the real bracket.Not here, filed as #4041: the assembler, and therefore log events and deadlocks, drops every line under a prefix with fields between the zone and the pid. Plan capture has accepted that shape since #4016. Fixing it changes the #3996-hardened reader shared by all log families, so it gets its own PR and review round.
Test plan
PgDeadlockLogParserTests: newAStatementCompanionEchoingAReport_IsNotReadAsOne(Deadlock capture's regexp_matches may accept a forged STATEMENT echo, same class as #4008 #4014's exact shape, plus a real report after it still reading) andAForgedHeaderBehindARealColonPrefixedBracket_IsNotReadAsOne.PgDeadlockCandidatePatternLiveTestsruns the shippedregexp_matchespattern, lifted fromBuildQuery, through PostgreSQL's own regex engine:%Q;Expected: 0, Actual: 1, the echo offered).TheTailerExtraction_LeftBothSiblingsSqlByteIdenticalupdated for the deadlock SQL.🤖 Generated with Claude Code
https://claude.ai/code/session_01GdmA4ND1wLSqA91ax1m4xv