Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 1ca3126

Browse files
committed
Clarify the checks in RegisterBackgroundWorker.
In EXEC_BACKEND or single-user mode, we process shared_preload_libraries at postmaster startup as usual, but also at backend startup. When a library calls RegisterBackgroundWorker() when being loaded into a backend process, we go through the motions to add the worker to BackgroundWorkerList, even though that is a postmaster-private data structure. Make it return early when called in a backend process, without changing BackgroundWorkerList. You could argue that it was intentional: In non-EXEC_BACKEND mode, the backend processes inherit BackgroundWorkerList at fork(), so it does make some sense to initialize it to the same state in EXEC_BACKEND mode, too. It's clearly a postmaster-private structure, though, and all the functions that use it are clearly marked as "should only be called in postmaster". You could also argue that libraries should not call RegisterBackgroundWorker() during backend startup. It's too late to correctly register any static background workers at that stage. But it's a common pattern in extensions, and it doesn't seem worth the churn to require all extensions to change it. Another sloppiness was the exception for "internal" background workers. We checked that RegisterBackgroundWorker() was called during shared_preload_libraries processing, or the background worker was an internal one. That exception was made in commit 665d1fa to allow postmaster to register the logical apply launcher in ApplyLauncherRegister(). The way the check was written, it would not complain if you registered an internal background worker in a regular backend process. But it would complain if postmaster registered a background worker defined in a shared library, outside shared_preload_libraries processing. I think the correct rule is that you can only register static background workers in the postmaster process, and only before the bgworker shared memory array has been initialized. Check for that more directly. Reviewed-by: Thomas Munro Discussion: https://www.postgresql.org/message-id/4f95c1fc-ad3c-7974-3a8c-6faa3931804c@iki.fi
1 parent 608fd19 commit 1ca3126

File tree

1 file changed

+33
-11
lines changed

1 file changed

+33
-11
lines changed

src/backend/postmaster/bgworker.c

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -880,21 +880,43 @@ RegisterBackgroundWorker(BackgroundWorker *worker)
880880
RegisteredBgWorker *rw;
881881
static int numworkers = 0;
882882

883-
if (!IsUnderPostmaster)
884-
ereport(DEBUG1,
885-
(errmsg_internal("registering background worker \"%s\"", worker->bgw_name)));
886-
887-
if (!process_shared_preload_libraries_in_progress &&
888-
strcmp(worker->bgw_library_name, "postgres") != 0)
883+
/*
884+
* Static background workers can only be registered in the postmaster
885+
* process.
886+
*/
887+
if (IsUnderPostmaster || !IsPostmasterEnvironment)
889888
{
890-
if (!IsUnderPostmaster)
891-
ereport(LOG,
892-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
893-
errmsg("background worker \"%s\": must be registered in shared_preload_libraries",
894-
worker->bgw_name)));
889+
/*
890+
* In EXEC_BACKEND or single-user mode, we process
891+
* shared_preload_libraries in backend processes too. We cannot
892+
* register static background workers at that stage, but many
893+
* libraries' _PG_init() functions don't distinguish whether they're
894+
* being loaded in the postmaster or in a backend, they just check
895+
* process_shared_preload_libraries_in_progress. It's a bit sloppy,
896+
* but for historical reasons we tolerate it. In EXEC_BACKEND mode,
897+
* the background workers should already have been registered when the
898+
* library was loaded in postmaster.
899+
*/
900+
if (process_shared_preload_libraries_in_progress)
901+
return;
902+
ereport(LOG,
903+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
904+
errmsg("background worker \"%s\": must be registered in shared_preload_libraries",
905+
worker->bgw_name)));
895906
return;
896907
}
897908

909+
/*
910+
* Cannot register static background workers after calling
911+
* BackgroundWorkerShmemInit().
912+
*/
913+
if (BackgroundWorkerData != NULL)
914+
elog(ERROR, "cannot register background worker \"%s\" after shmem init",
915+
worker->bgw_name);
916+
917+
ereport(DEBUG1,
918+
(errmsg_internal("registering background worker \"%s\"", worker->bgw_name)));
919+
898920
if (!SanityCheckBackgroundWorker(worker, LOG))
899921
return;
900922

0 commit comments

Comments
 (0)