]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Improve timeout handling of pg_promote()
authorMichael Paquier <michael@paquier.xyz>
Thu, 26 Mar 2026 01:39:40 +0000 (10:39 +0900)
committerMichael Paquier <michael@paquier.xyz>
Thu, 26 Mar 2026 01:39:40 +0000 (10:39 +0900)
Previously, pg_promote() looped a fixed number of times, calculated from
the specified timeout, and waited 100ms on a latch, once per iteration,
for the promotion of a standby to complete.  However, unrelated signals
to the backend could set the latch and wake up the backend early,
resulting in a faster consumption of the loops and an execution time of
the function that does not match with the timeout input given in input.
This could be confusing for the function caller, especially if some
backend-side timeout is aggressive, because the function would return
much earlier than expected and report that the promote request has not
completed within the time requested.

This commit refines the logic to track the time actually elapsed, by
looping until the requested duration has truly passed.  The code
calculates the end time we expect, then uses it when looping.

Author: Robert Pang <robertpang@google.com>
Reviewed-by: Tiancheng Ge <getiancheng_2012@163.com>
Discussion: https://postgr.es/m/CAJhEC07OK8J7tLUbyiccnuOXRE7UKxBNqD2-pLfeFXa=tBoWtw@mail.gmail.com

src/backend/access/transam/xlogfuncs.c

index 4e35311b2f357fb7f4930e66677fc6d0feef1ca2..65bbaeda59c4e707ab484c5f50bef4337793f87f 100644 (file)
@@ -691,7 +691,7 @@ pg_promote(PG_FUNCTION_ARGS)
        bool            wait = PG_GETARG_BOOL(0);
        int                     wait_seconds = PG_GETARG_INT32(1);
        FILE       *promote_file;
-       int                     i;
+       TimestampTz end_time;
 
        if (!RecoveryInProgress())
                ereport(ERROR,
@@ -732,8 +732,8 @@ pg_promote(PG_FUNCTION_ARGS)
                PG_RETURN_BOOL(true);
 
        /* wait for the amount of time wanted until promotion */
-#define WAITS_PER_SECOND 10
-       for (i = 0; i < WAITS_PER_SECOND * wait_seconds; i++)
+       end_time = TimestampTzPlusSeconds(GetCurrentTimestamp(), wait_seconds);
+       while (GetCurrentTimestamp() < end_time)
        {
                int                     rc;
 
@@ -746,7 +746,7 @@ pg_promote(PG_FUNCTION_ARGS)
 
                rc = WaitLatch(MyLatch,
                                           WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
-                                          1000L / WAITS_PER_SECOND,
+                                          100L,
                                           WAIT_EVENT_PROMOTE);
 
                /*