]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Handle checksumworker startup wait race
authorDaniel Gustafsson <dgustafsson@postgresql.org>
Sun, 5 Apr 2026 23:55:06 +0000 (01:55 +0200)
committerDaniel Gustafsson <dgustafsson@postgresql.org>
Sun, 5 Apr 2026 23:55:06 +0000 (01:55 +0200)
If the background worker for processing databases manages to finish
before the launcher starts waiting for it, the launcher would treat
it erroneously as an error.  Fix by ensureing to check result state
in this case.  Identified on CI and synthetically reproduced during
local testing.

Also while, make sure to properly lock the shared memory structure
before updating tje result state.

Author: Daniel Gustafsson <daniel@yesql.seA
Reported-by: Andres Freund <andres@anarazel.de>
Discussion: https://postgr.es/m/4fxw37ge47v5baeozla5phymi233hxbcjbwwsfwv3mpg3kyl2z@6jk4nkf6jp4

src/backend/postmaster/datachecksum_state.c

index eb7b01d0993677643c3b857f6701a4f2902c3d84..430e6e9a3c9bacf38c15d264952bdf9203e5d11b 100644 (file)
@@ -797,6 +797,19 @@ ProcessDatabase(DataChecksumsWorkerDatabase *db)
        status = WaitForBackgroundWorkerStartup(bgw_handle, &pid);
        if (status == BGWH_STOPPED)
        {
+               /*
+                * If the worker managed to start, and stop, before we got to waiting
+                * for it we can se a STOPPED status here without it being a failure.
+                */
+               if (DataChecksumState->success == DATACHECKSUMSWORKER_SUCCESSFUL)
+               {
+                       pgstat_report_activity(STATE_IDLE, NULL);
+                       LWLockAcquire(DataChecksumsWorkerLock, LW_EXCLUSIVE);
+                       DataChecksumState->worker_pid = InvalidPid;
+                       LWLockRelease(DataChecksumsWorkerLock);
+                       return DataChecksumState->success;
+               }
+
                ereport(WARNING,
                                errmsg("could not start background worker for enabling data checksums in database \"%s\"",
                                           db->dbname),
@@ -1595,5 +1608,7 @@ DataChecksumsWorkerMain(Datum arg)
        /* worker done */
        pgstat_progress_end_command();
 
+       LWLockAcquire(DataChecksumsWorkerLock, LW_EXCLUSIVE);
        DataChecksumState->success = DATACHECKSUMSWORKER_SUCCESSFUL;
+       LWLockRelease(DataChecksumsWorkerLock);
 }