Re: failures in t/031_recovery_conflict.pl on CI
Andres Freund <andres@anarazel.de>
From: Andres Freund <andres@anarazel.de>
To: pgsql-hackers@postgresql.org, Thomas Munro <thomas.munro@gmail.com>
Date: 2022-04-09T22:00:54Z
Lists: pgsql-hackers
Hi,
On 2022-04-08 22:05:01 -0700, Andres Freund wrote:
> On 2022-04-08 21:55:15 -0700, Andres Freund wrote:
> > on CI [1] the new t/031_recovery_conflict.pl is failing occasionally. Which is
> > interesting, because I ran it there dozens if not hundreds of times before
> > commit, with - I think - only cosmetic changes.
>
> Scratch that part - I found an instance of the freebsd failure earlier, just
> didn't notice because that run failed for other reasons as well. So this might
> just have uncovered an older bug around recovery conflict handling,
> potentially platform dependent.
>
> I guess I'll try to reproduce it on freebsd...
That failed.
Adding a bunch of debug statements, I think I might have found at least some
problems.
The code in LockBufferForCleanup() that actually interacts with other backends
is:
/* Publish the bufid that Startup process waits on */
SetStartupBufferPinWaitBufId(buffer - 1);
/* Set alarm and then wait to be signaled by UnpinBuffer() */
ResolveRecoveryConflictWithBufferPin();
/* Reset the published bufid */
SetStartupBufferPinWaitBufId(-1);
where ResolveRecoveryConflictWithBufferPin() sends procsignals to all other
backends and then waits with ProcWaitForSignal():
void
ProcWaitForSignal(uint32 wait_event_info)
{
(void) WaitLatch(MyLatch, WL_LATCH_SET | WL_EXIT_ON_PM_DEATH, 0,
wait_event_info);
ResetLatch(MyLatch);
CHECK_FOR_INTERRUPTS();
}
one problem is that we pretty much immediately get a SIGALRM whenever we're in
that WaitLatch(). Which does a SetLatch(), interrupting the WaitLatch(). The
startup process then proceeds to SetStartupBufferPinWaitBufId(-1).
In the unlucky cases, the backend holding the pin only processes the interrupt
(in RecoveryConflictInterrupt()) after the
SetStartupBufferPinWaitBufId(-1). The backend then does sees that
HoldingBufferPinThatDelaysRecovery() returns false, and happily continues.
But that's not the whole story, I think. It's a problem leading to conflicts
being handled more slowly, but we eventually should not have more timeouts.
Here's debugging output from a failing run, where I added a few debugging statements:
https://api.cirrus-ci.com/v1/artifact/task/6179111512047616/log/src/test/recovery/tmp_check/log/000_0recovery_conflict_standby.log
https://github.com/anarazel/postgres/commit/212268e753093861aa22a51657c6598c65eeb81b
Curiously, there's only
20644: received interrupt 11
Which is PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK, not
PROCSIG_RECOVERY_CONFLICT_BUFFERPIN.
I guess we've never gotten past the standby timeout.
20644: received interrupt 11
2022-04-09 21:18:23.824 UTC [20630][startup] DEBUG: one cycle of LockBufferForCleanup() iterating in HS
2022-04-09 21:18:23.824 UTC [20630][startup] CONTEXT: WAL redo at 0/3432800 for Heap2/PRUNE: latestRemovedXid 0 nredirected 0 ndead 1; blkref #0: rel 1663/16385/16386, blk 0
2022-04-09 21:18:23.824 UTC [20630][startup] DEBUG: setting timeout() in 0 10000
2022-04-09 21:18:23.824 UTC [20630][startup] CONTEXT: WAL redo at 0/3432800 for Heap2/PRUNE: latestRemovedXid 0 nredirected 0 ndead 1; blkref #0: rel 1663/16385/16386, blk 0
2022-04-09 21:18:23.835 UTC [20630][startup] DEBUG: setting latch()
2022-04-09 21:18:23.835 UTC [20630][startup] CONTEXT: WAL redo at 0/3432800 for Heap2/PRUNE: latestRemovedXid 0 nredirected 0 ndead 1; blkref #0: rel 1663/16385/16386, blk 0
2022-04-09 21:18:23.835 UTC [20630][startup] DEBUG: setting timeout() in 0 3481
2022-04-09 21:18:23.835 UTC [20630][startup] CONTEXT: WAL redo at 0/3432800 for Heap2/PRUNE: latestRemovedXid 0 nredirected 0 ndead 1; blkref #0: rel 1663/16385/16386, blk 0
20644: received interrupt 11
2022-04-09 21:23:47.975 UTC [20631][walreceiver] FATAL: could not receive data from WAL stream: server closed the connection unexpectedly
So we sent a conflict interrupt, and then waited. And nothing happened.
What are we expecting to wake the startup process up, once it does
SendRecoveryConflictWithBufferPin()?
It's likely not the problem here, because we never seem to have even reached
that path, but afaics once we've called disable_all_timeouts() at the bottom
of ResolveRecoveryConflictWithBufferPin() and then re-entered
ResolveRecoveryConflictWithBufferPin(), and go into the "We're already behind,
so clear a path as quickly as possible." path, there's no guarantee for any
timeout to be pending anymore?
If there's either no backend that we're still conflicting with (an entirely
possible race condition), or if there's e.g. a snapshot or database conflict,
there's afaics nobody setting the startup processes' latch.
Greetings,
Andres Freund
Commits
-
Disable 031_recovery_conflict.pl until after minor releases.
- 390b489eff76 10.21 landed
- 4caa29414d60 11.16 landed
- 1e1542833e8c 12.11 landed
- 6348e4685068 13.7 landed
- 55e5a5e0fa16 14.3 landed
-
Temporarily skip recovery deadlock test in back branches.
- 441fa7a63ad4 10.21 landed
- fb965ab0f641 11.16 landed
- 26f9e21cb63e 12.11 landed
- 4e39957e6eb5 13.7 landed
- f40d362a667f 14.3 landed
-
Backpatch addition of pump_until() more completely.
- 47f47a8d4738 11.16 landed
- fbf659bc4040 12.11 landed
- 6ab90d215afc 13.7 landed
- 7fa95bb0ac8e 14.3 landed
-
Fix timing issue in deadlock recovery conflict test.
- 3197e0f5ae9d 10.21 landed
- 7a1267f9fe74 11.16 landed
- 512d76f6dbda 12.11 landed
- 8a3a8d9f103e 13.7 landed
- 5136967f1eb1 14.3 landed
- 9e6b7b45ca92 15.0 landed
-
Backpatch 031_recovery_conflict.pl.
- b1f35a36e6d5 10.21 landed
- 25d5494e2841 11.16 landed
- a5ede13916f3 12.11 landed
- 0446d3bf3909 13.7 landed
- f74496dd611e 14.3 landed
-
Fix possibility of self-deadlock in ResolveRecoveryConflictWithBufferPin().
- cbc47ad7ef60 10.21 landed
- 9cda785b4ea3 11.16 landed
- edfc03ec91f2 12.11 landed
- 57c5ad168be1 13.7 landed
- 9ab3b2bdbb5d 14.3 landed
- 8f1537d10e83 15.0 landed
-
Backpatch addition of wait_for_log(), pump_until().
- e8a0cf9b20a1 10.21 landed
- 2adb8debe5aa 11.16 landed
- 90abe1e17f9d 13.7 landed
- 5c8b14a71d31 12.11 landed
- 5ab8e8014801 14.3 landed
-
Add tests for recovery deadlock conflicts.
- 21e184403bf9 15.0 landed
-
Phase 3 of pgindent updates.
- 382ceffdf7f6 10.0 cited