Skip to content

test: the row-identity lock arms wait for the holder's UPDATE to finish; main is red on them (#1368) - #1390

Merged
jdatcmd merged 1 commit into
commandprompt:mainfrom
OffgridwithJD:fix/1368-row-lock-race
Oct 14, 2026
Merged

jdatcmd merged 1 commit into
commandprompt:mainfrom
OffgridwithJD:fix/1368-row-lock-race

Conversation

@OffgridwithJD

Copy link
Copy Markdown
Collaborator

Main is red at f601281 (push run 38586686502, suites (PG 17)), and #1364 fails the same way on PG 18:

FAIL  an UPDATE holds a row-identity lock (class 104) while enable_row_update_lock is on: got [none|1] want [held|1]

Cause

#1368's shell arm polls until the holder's UPDATE is "running", using the holder's RowExclusiveLock on rl as the signal. The UPDATE takes that lock at executor start, before it reaches row 7 and takes the class-104 advisory lock. A poll that lands in between reads none|1. I approved that proxy in review, and this is the fix.

The off arm has the same hole in the other direction: a 0 read in that window could mean "not there yet". The pytest twin is unaffected, because it reads pg_locks only after its UPDATE has returned.

Fix (shell only)

  • The holder sets application_name = 'rl_updated_<setting>' after its UPDATE returns, and the poll waits for that name.
  • A WITH d AS MATERIALIZED (SELECT pg_sleep(1)) ahead of the row keeps the window open on every run. A return to an early signal then fails every time instead of now and then.

Evidence (PG17 unless noted)

result
window widened, old poll (red first) 3/3 runs: `got [none
window widened, new poll 3/3 runs: 10/10
mutant: setting ignored (lock taken with it off) red: `and holds none with enable_row_update_lock off: got [1
mutant: never takes the row lock red: `... while enable_row_update_lock is on: got [none
clean on 15, 16, 18, 19 10/10 each

No ledger change: advisory_lock_class has no rows yet. The suite costs about 2 s more (1 s per holder).

🤖 Generated with Claude Code

…sh, not to start; main was red on it (commandprompt#1368)

The poll waited for the holder's RowExclusiveLock on rl, which the UPDATE takes at
executor start, before it reaches row 7 and takes the class-104 lock. A poll in
between read "none|1": main f601281 failed on PG 17, and commandprompt#1364 on PG 18. The holder
now names itself in application_name after its UPDATE returns, and the poll waits
for that. A CTE sleep ahead of the row keeps the window open on every run, so a
return to the early event fails every time rather than now and then.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VjTxfQJj5pnii9wzmPP9Ho
@OffgridwithJD

Copy link
Copy Markdown
Collaborator Author

@jdatcmd CI is green on #1390 (15/15, including both suites jobs that are red on main). It's shell-only and a few lines, and it unblocks main plus the rerun on #1364. Please review and merge when you can. Evidence is in the description: red first 3/3 with CI's exact failure text, both mutants red, clean on 15–19.

🤖 Generated with Claude Code

@jdatcmd jdatcmd left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reproduced at 0eb19bb.

run result
main's poll, with the PR's 1 s window added (PG17) 9/10: `an UPDATE holds a row-identity lock (class 104) while enable_row_update_lock is on: got [none
this PR (PG17, PG18) 10/10 each

The new signal is the right event. The application_name assignment reports to pg_stat_activity at once, after the UPDATE returns and while the transaction still holds its locks for the 3 s sleep. If the UPDATE errors, the name is never set and the poll ends on |0, so the arm fails loudly rather than reading too early.

Approving. I'll merge it now, since main is red on this race.

🤖 Generated with Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants