From 7f7485a0cde92aa4ba235a1ffe4dda0ca0b6cc9a Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Tue, 16 Jul 2013 13:02:15 -0400 Subject: Allow background workers to be started dynamically. There is a new API, RegisterDynamicBackgroundWorker, which allows an ordinary user backend to register a new background writer during normal running. This means that it's no longer necessary for all background workers to be registered during processing of shared_preload_libraries, although the option of registering workers at that time remains available. When a background worker exits and will not be restarted, the slot previously used by that background worker is automatically released and becomes available for reuse. Slots used by background workers that are configured for automatic restart can't (yet) be released without shutting down the system. This commit adds a new source file, bgworker.c, and moves some of the existing control logic for background workers there. Previously, there was little enough logic that it made sense to keep everything in postmaster.c, but not any more. This commit also makes the worker_spi contrib module into an extension and adds a new function, worker_spi_launch, which can be used to demonstrate the new facility. --- doc/src/sgml/bgworker.sgml | 55 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 9 deletions(-) (limited to 'doc/src') diff --git a/doc/src/sgml/bgworker.sgml b/doc/src/sgml/bgworker.sgml index f7126388af1..9d9b631ac1a 100644 --- a/doc/src/sgml/bgworker.sgml +++ b/doc/src/sgml/bgworker.sgml @@ -30,23 +30,35 @@ - Only modules listed in shared_preload_libraries can run - background workers. A module wishing to run a background worker needs - to register it by calling + Background workers can be initialized at the time that + PostgreSQL is started including the module name in + shared_preload_libraries. A module wishing to run a background + worker can register it by calling RegisterBackgroundWorker(BackgroundWorker *worker) - from its _PG_init(). + from its _PG_init(). Background workers can also be started + after the system is up and running by calling the function + RegisterDynamicBackgroundWorker(BackgroundWorker + *worker). Unlike RegisterBackgroundWorker, which can + only be called from within the postmaster, + RegisterDynamicBackgroundWorker must be called from + a regular backend. + + + The structure BackgroundWorker is defined thus: typedef void (*bgworker_main_type)(void *main_arg); typedef void (*bgworker_sighdlr_type)(SIGNAL_ARGS); typedef struct BackgroundWorker { - char *bgw_name; + char bgw_name[BGW_MAXLEN]; int bgw_flags; BgWorkerStartTime bgw_start_time; int bgw_restart_time; /* in seconds, or BGW_NEVER_RESTART */ - bgworker_main_type bgw_main; - void *bgw_main_arg; + bgworker_main_type bgw_main; + char bgw_library_name[BGW_MAXLEN]; /* only if bgw_main is NULL */ + char bgw_function_name[BGW_MAXLEN]; /* only if bgw_main is NULL */ + Datum bgw_main_arg; bgworker_sighdlr_type bgw_sighup; bgworker_sighdlr_type bgw_sigterm; } BackgroundWorker; @@ -101,7 +113,29 @@ typedef struct BackgroundWorker bgw_main_arg will be passed to it as its only argument. Note that the global variable MyBgworkerEntry points to a copy of the BackgroundWorker structure - passed at registration time. + passed at registration time. bgw_main may be + NULL; in that case, bgw_library_name and + bgw_function_name will be used to determine + the entrypoint. This is useful for background workers launched after + postmaster startup, where the postmaster does not have the requisite + library loaded. + + + + bgw_library_name is the name of a library in + which the initial entrypoint for the background worker should be sought. + It is ignored unless bgw_main is NULL. + But if bgw_main is NULL, then the named library + will be dynamically loaded by the worker process and + bgw_function_name will be used to identify + the function to be called. + + + + bgw_function_name is the name of a function in + a dynamically loaded library which should be used as the initial entrypoint + for a new background worker. It is ignored unless + bgw_main is NULL. @@ -109,7 +143,10 @@ typedef struct BackgroundWorker pointers to functions that will be installed as signal handlers for the new process. If bgw_sighup is NULL, then SIG_IGN is used; if bgw_sigterm is NULL, a handler is installed that - will terminate the process after logging a suitable message. + will terminate the process after logging a suitable message. These + fields should not be used if bgw_main is NULL; instead, + the worker process should set its own signal handlers before calling + BackgroundWorkerUnblockSignals(). Once running, the process can connect to a database by calling -- cgit v1.2.3