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.
13 years ago
|
|
|
/*--------------------------------------------------------------------
|
|
|
|
|
* bgworker.c
|
|
|
|
|
* POSTGRES pluggable background workers implementation
|
|
|
|
|
*
|
|
|
|
|
* Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
|
|
|
|
|
*
|
|
|
|
|
* IDENTIFICATION
|
|
|
|
|
* src/backend/postmaster/bgworker.c
|
|
|
|
|
*
|
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "postgres.h"
|
|
|
|
|
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <time.h>
|
|
|
|
|
|
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.
13 years ago
|
|
|
#include "miscadmin.h"
|
|
|
|
|
#include "libpq/pqsignal.h"
|
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.
13 years ago
|
|
|
#include "postmaster/bgworker_internals.h"
|
|
|
|
|
#include "storage/barrier.h"
|
|
|
|
|
#include "storage/ipc.h"
|
|
|
|
|
#include "storage/latch.h"
|
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.
13 years ago
|
|
|
#include "storage/lwlock.h"
|
|
|
|
|
#include "storage/pmsignal.h"
|
|
|
|
|
#include "storage/proc.h"
|
|
|
|
|
#include "storage/procsignal.h"
|
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.
13 years ago
|
|
|
#include "storage/shmem.h"
|
|
|
|
|
#include "tcop/tcopprot.h"
|
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.
13 years ago
|
|
|
#include "utils/ascii.h"
|
|
|
|
|
#include "utils/ps_status.h"
|
|
|
|
|
#include "utils/timeout.h"
|
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.
13 years ago
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* The postmaster's list of registered background workers, in private memory.
|
|
|
|
|
*/
|
|
|
|
|
slist_head BackgroundWorkerList = SLIST_STATIC_INIT(BackgroundWorkerList);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* BackgroundWorkerSlots exist in shared memory and can be accessed (via
|
|
|
|
|
* the BackgroundWorkerArray) by both the postmaster and by regular backends.
|
|
|
|
|
* However, the postmaster cannot take locks, even spinlocks, because this
|
|
|
|
|
* might allow it to crash or become wedged if shared memory gets corrupted.
|
|
|
|
|
* Such an outcome is intolerable. Therefore, we need a lockless protocol
|
|
|
|
|
* for coordinating access to this data.
|
|
|
|
|
*
|
|
|
|
|
* The 'in_use' flag is used to hand off responsibility for the slot between
|
|
|
|
|
* the postmaster and the rest of the system. When 'in_use' is false,
|
|
|
|
|
* the postmaster will ignore the slot entirely, except for the 'in_use' flag
|
|
|
|
|
* itself, which it may read. In this state, regular backends may modify the
|
|
|
|
|
* slot. Once a backend sets 'in_use' to true, the slot becomes the
|
|
|
|
|
* responsibility of the postmaster. Regular backends may no longer modify it,
|
|
|
|
|
* but the postmaster may examine it. Thus, a backend initializing a slot
|
|
|
|
|
* must fully initialize the slot - and insert a write memory barrier - before
|
|
|
|
|
* marking it as in use.
|
|
|
|
|
*
|
|
|
|
|
* In addition to coordinating with the postmaster, backends modifying this
|
|
|
|
|
* data structure must coordinate with each other. Since they can take locks,
|
|
|
|
|
* this is straightforward: any backend wishing to manipulate a slot must
|
|
|
|
|
* take BackgroundWorkerLock in exclusive mode. Backends wishing to read
|
|
|
|
|
* data that might get concurrently modified by other backends should take
|
|
|
|
|
* this lock in shared mode. No matter what, backends reading this data
|
|
|
|
|
* structure must be able to tolerate concurrent modifications by the
|
|
|
|
|
* postmaster.
|
|
|
|
|
*/
|
|
|
|
|
typedef struct BackgroundWorkerSlot
|
|
|
|
|
{
|
|
|
|
|
bool in_use;
|
|
|
|
|
BackgroundWorker worker;
|
|
|
|
|
} BackgroundWorkerSlot;
|
|
|
|
|
|
|
|
|
|
typedef struct BackgroundWorkerArray
|
|
|
|
|
{
|
|
|
|
|
int total_slots;
|
|
|
|
|
BackgroundWorkerSlot slot[FLEXIBLE_ARRAY_MEMBER];
|
|
|
|
|
} BackgroundWorkerArray;
|
|
|
|
|
|
|
|
|
|
BackgroundWorkerArray *BackgroundWorkerData;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Calculate shared memory needed.
|
|
|
|
|
*/
|
|
|
|
|
Size
|
|
|
|
|
BackgroundWorkerShmemSize(void)
|
|
|
|
|
{
|
|
|
|
|
Size size;
|
|
|
|
|
|
|
|
|
|
/* Array of workers is variably sized. */
|
|
|
|
|
size = offsetof(BackgroundWorkerArray, slot);
|
|
|
|
|
size = add_size(size, mul_size(max_worker_processes,
|
|
|
|
|
sizeof(BackgroundWorkerSlot)));
|
|
|
|
|
|
|
|
|
|
return size;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Initialize shared memory.
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
BackgroundWorkerShmemInit(void)
|
|
|
|
|
{
|
|
|
|
|
bool found;
|
|
|
|
|
|
|
|
|
|
BackgroundWorkerData = ShmemInitStruct("Background Worker Data",
|
|
|
|
|
BackgroundWorkerShmemSize(),
|
|
|
|
|
&found);
|
|
|
|
|
if (!IsUnderPostmaster)
|
|
|
|
|
{
|
|
|
|
|
slist_iter siter;
|
|
|
|
|
int slotno = 0;
|
|
|
|
|
|
|
|
|
|
BackgroundWorkerData->total_slots = max_worker_processes;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Copy contents of worker list into shared memory. Record the
|
|
|
|
|
* shared memory slot assigned to each worker. This ensures
|
|
|
|
|
* a 1-to-1 correspondence betwen the postmaster's private list and
|
|
|
|
|
* the array in shared memory.
|
|
|
|
|
*/
|
|
|
|
|
slist_foreach(siter, &BackgroundWorkerList)
|
|
|
|
|
{
|
|
|
|
|
BackgroundWorkerSlot *slot = &BackgroundWorkerData->slot[slotno];
|
|
|
|
|
RegisteredBgWorker *rw;
|
|
|
|
|
|
|
|
|
|
rw = slist_container(RegisteredBgWorker, rw_lnode, siter.cur);
|
|
|
|
|
Assert(slotno < max_worker_processes);
|
|
|
|
|
slot->in_use = true;
|
|
|
|
|
rw->rw_shmem_slot = slotno;
|
|
|
|
|
memcpy(&slot->worker, &rw->rw_worker, sizeof(BackgroundWorker));
|
|
|
|
|
++slotno;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Mark any remaining slots as not in use.
|
|
|
|
|
*/
|
|
|
|
|
while (slotno < max_worker_processes)
|
|
|
|
|
{
|
|
|
|
|
BackgroundWorkerSlot *slot = &BackgroundWorkerData->slot[slotno];
|
|
|
|
|
|
|
|
|
|
slot->in_use = false;
|
|
|
|
|
++slotno;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
Assert(found);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Search the postmaster's backend-private list of RegisteredBgWorker objects
|
|
|
|
|
* for the one that maps to the given slot number.
|
|
|
|
|
*/
|
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.
13 years ago
|
|
|
static RegisteredBgWorker *
|
|
|
|
|
FindRegisteredWorkerBySlotNumber(int slotno)
|
|
|
|
|
{
|
|
|
|
|
slist_iter siter;
|
|
|
|
|
|
|
|
|
|
slist_foreach(siter, &BackgroundWorkerList)
|
|
|
|
|
{
|
|
|
|
|
RegisteredBgWorker *rw;
|
|
|
|
|
|
|
|
|
|
rw = slist_container(RegisteredBgWorker, rw_lnode, siter.cur);
|
|
|
|
|
if (rw->rw_shmem_slot == slotno)
|
|
|
|
|
return rw;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Notice changes to shared memory made by other backends. This code
|
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.
13 years ago
|
|
|
* runs in the postmaster, so we must be very careful not to assume that
|
|
|
|
|
* shared memory contents are sane. Otherwise, a rogue backend could take
|
|
|
|
|
* out the postmaster.
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
BackgroundWorkerStateChange(void)
|
|
|
|
|
{
|
|
|
|
|
int slotno;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* The total number of slots stored in shared memory should match our
|
|
|
|
|
* notion of max_worker_processes. If it does not, something is very
|
|
|
|
|
* wrong. Further down, we always refer to this value as
|
|
|
|
|
* max_worker_processes, in case shared memory gets corrupted while
|
|
|
|
|
* we're looping.
|
|
|
|
|
*/
|
|
|
|
|
if (max_worker_processes != BackgroundWorkerData->total_slots)
|
|
|
|
|
{
|
|
|
|
|
elog(LOG,
|
|
|
|
|
"inconsistent background worker state (max_worker_processes=%d, total_slots=%d",
|
|
|
|
|
max_worker_processes,
|
|
|
|
|
BackgroundWorkerData->total_slots);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Iterate through slots, looking for newly-registered workers or
|
|
|
|
|
* workers who must die.
|
|
|
|
|
*/
|
|
|
|
|
for (slotno = 0; slotno < max_worker_processes; ++slotno)
|
|
|
|
|
{
|
|
|
|
|
BackgroundWorkerSlot *slot = &BackgroundWorkerData->slot[slotno];
|
|
|
|
|
RegisteredBgWorker *rw;
|
|
|
|
|
|
|
|
|
|
if (!slot->in_use)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Make sure we don't see the in_use flag before the updated slot
|
|
|
|
|
* contents.
|
|
|
|
|
*/
|
|
|
|
|
pg_read_barrier();
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* See whether we already know about this worker. If not, we need
|
|
|
|
|
* to update our backend-private BackgroundWorkerList to match shared
|
|
|
|
|
* memory.
|
|
|
|
|
*/
|
|
|
|
|
rw = FindRegisteredWorkerBySlotNumber(slotno);
|
|
|
|
|
if (rw != NULL)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Copy the registration data into the registered workers list.
|
|
|
|
|
*/
|
|
|
|
|
rw = malloc(sizeof(RegisteredBgWorker));
|
|
|
|
|
if (rw == NULL)
|
|
|
|
|
{
|
|
|
|
|
ereport(LOG,
|
|
|
|
|
(errcode(ERRCODE_OUT_OF_MEMORY),
|
|
|
|
|
errmsg("out of memory")));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Copy strings in a paranoid way. If shared memory is corrupted,
|
|
|
|
|
* the source data might not even be NUL-terminated.
|
|
|
|
|
*/
|
|
|
|
|
ascii_safe_strlcpy(rw->rw_worker.bgw_name,
|
|
|
|
|
slot->worker.bgw_name, BGW_MAXLEN);
|
|
|
|
|
ascii_safe_strlcpy(rw->rw_worker.bgw_library_name,
|
|
|
|
|
slot->worker.bgw_library_name, BGW_MAXLEN);
|
|
|
|
|
ascii_safe_strlcpy(rw->rw_worker.bgw_function_name,
|
|
|
|
|
slot->worker.bgw_function_name, BGW_MAXLEN);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Copy remaining fields.
|
|
|
|
|
*
|
|
|
|
|
* flags, start_time, and restart_time are examined by the
|
|
|
|
|
* postmaster, but nothing too bad will happen if they are
|
|
|
|
|
* corrupted. The remaining fields will only be examined by the
|
|
|
|
|
* child process. It might crash, but we won't.
|
|
|
|
|
*/
|
|
|
|
|
rw->rw_worker.bgw_flags = slot->worker.bgw_flags;
|
|
|
|
|
rw->rw_worker.bgw_start_time = slot->worker.bgw_start_time;
|
|
|
|
|
rw->rw_worker.bgw_restart_time = slot->worker.bgw_restart_time;
|
|
|
|
|
rw->rw_worker.bgw_main = slot->worker.bgw_main;
|
|
|
|
|
rw->rw_worker.bgw_main_arg = slot->worker.bgw_main_arg;
|
|
|
|
|
|
|
|
|
|
/* Initialize postmaster bookkeeping. */
|
|
|
|
|
rw->rw_backend = NULL;
|
|
|
|
|
rw->rw_pid = 0;
|
|
|
|
|
rw->rw_child_slot = 0;
|
|
|
|
|
rw->rw_crashed_at = 0;
|
|
|
|
|
rw->rw_shmem_slot = slotno;
|
|
|
|
|
|
|
|
|
|
/* Log it! */
|
|
|
|
|
ereport(LOG,
|
|
|
|
|
(errmsg("registering background worker \"%s\"",
|
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.
13 years ago
|
|
|
rw->rw_worker.bgw_name)));
|
|
|
|
|
|
|
|
|
|
slist_push_head(&BackgroundWorkerList, &rw->rw_lnode);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Forget about a background worker that's no longer needed.
|
|
|
|
|
*
|
|
|
|
|
* The worker must be identified by passing an slist_mutable_iter that
|
|
|
|
|
* points to it. This convention allows deletion of workers during
|
|
|
|
|
* searches of the worker list, and saves having to search the list again.
|
|
|
|
|
*
|
|
|
|
|
* This function must be invoked only in the postmaster.
|
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.
13 years ago
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
ForgetBackgroundWorker(slist_mutable_iter *cur)
|
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.
13 years ago
|
|
|
{
|
|
|
|
|
RegisteredBgWorker *rw;
|
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.
13 years ago
|
|
|
BackgroundWorkerSlot *slot;
|
|
|
|
|
|
|
|
|
|
rw = slist_container(RegisteredBgWorker, rw_lnode, cur->cur);
|
|
|
|
|
|
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.
13 years ago
|
|
|
Assert(rw->rw_shmem_slot < max_worker_processes);
|
|
|
|
|
slot = &BackgroundWorkerData->slot[rw->rw_shmem_slot];
|
|
|
|
|
slot->in_use = false;
|
|
|
|
|
|
|
|
|
|
ereport(LOG,
|
|
|
|
|
(errmsg("unregistering background worker \"%s\"",
|
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.
13 years ago
|
|
|
rw->rw_worker.bgw_name)));
|
|
|
|
|
|
|
|
|
|
slist_delete_current(cur);
|
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.
13 years ago
|
|
|
free(rw);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef EXEC_BACKEND
|
|
|
|
|
/*
|
|
|
|
|
* In EXEC_BACKEND mode, workers use this to retrieve their details from
|
|
|
|
|
* shared memory.
|
|
|
|
|
*/
|
|
|
|
|
BackgroundWorker *
|
|
|
|
|
BackgroundWorkerEntry(int slotno)
|
|
|
|
|
{
|
|
|
|
|
BackgroundWorkerSlot *slot;
|
|
|
|
|
|
|
|
|
|
Assert(slotno < BackgroundWorkerData->total_slots);
|
|
|
|
|
slot = &BackgroundWorkerData->slot[slotno];
|
|
|
|
|
Assert(slot->in_use);
|
|
|
|
|
return &slot->worker; /* can't become free while we're still here */
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Complain about the BackgroundWorker definition using error level elevel.
|
|
|
|
|
* Return true if it looks ok, false if not (unless elevel >= ERROR, in
|
|
|
|
|
* which case we won't return at all in the not-OK case).
|
|
|
|
|
*/
|
|
|
|
|
static bool
|
|
|
|
|
SanityCheckBackgroundWorker(BackgroundWorker *worker, int elevel)
|
|
|
|
|
{
|
|
|
|
|
/* sanity check for flags */
|
|
|
|
|
if (worker->bgw_flags & BGWORKER_BACKEND_DATABASE_CONNECTION)
|
|
|
|
|
{
|
|
|
|
|
if (!(worker->bgw_flags & BGWORKER_SHMEM_ACCESS))
|
|
|
|
|
{
|
|
|
|
|
ereport(elevel,
|
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
|
errmsg("background worker \"%s\": must attach to shared memory in order to request a database connection",
|
|
|
|
|
worker->bgw_name)));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (worker->bgw_start_time == BgWorkerStart_PostmasterStart)
|
|
|
|
|
{
|
|
|
|
|
ereport(elevel,
|
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
|
errmsg("background worker \"%s\": cannot request database access if starting at postmaster start",
|
|
|
|
|
worker->bgw_name)));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* XXX other checks? */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((worker->bgw_restart_time < 0 &&
|
|
|
|
|
worker->bgw_restart_time != BGW_NEVER_RESTART) ||
|
|
|
|
|
(worker->bgw_restart_time > USECS_PER_DAY / 1000))
|
|
|
|
|
{
|
|
|
|
|
ereport(elevel,
|
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
|
errmsg("background worker \"%s\": invalid restart interval",
|
|
|
|
|
worker->bgw_name)));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
bgworker_quickdie(SIGNAL_ARGS)
|
|
|
|
|
{
|
|
|
|
|
sigaddset(&BlockSig, SIGQUIT); /* prevent nested calls */
|
|
|
|
|
PG_SETMASK(&BlockSig);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* We DO NOT want to run proc_exit() callbacks -- we're here because
|
|
|
|
|
* shared memory may be corrupted, so we don't want to try to clean up our
|
|
|
|
|
* transaction. Just nail the windows shut and get out of town. Now that
|
|
|
|
|
* there's an atexit callback to prevent third-party code from breaking
|
|
|
|
|
* things by calling exit() directly, we have to reset the callbacks
|
|
|
|
|
* explicitly to make this work as intended.
|
|
|
|
|
*/
|
|
|
|
|
on_exit_reset();
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Note we do exit(0) here, not exit(2) like quickdie. The reason is that
|
|
|
|
|
* we don't want to be seen this worker as independently crashed, because
|
|
|
|
|
* then postmaster would delay restarting it again afterwards. If some
|
|
|
|
|
* idiot DBA manually sends SIGQUIT to a random bgworker, the "dead man
|
|
|
|
|
* switch" will ensure that postmaster sees this as a crash.
|
|
|
|
|
*/
|
|
|
|
|
exit(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Standard SIGTERM handler for background workers
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
bgworker_die(SIGNAL_ARGS)
|
|
|
|
|
{
|
|
|
|
|
PG_SETMASK(&BlockSig);
|
|
|
|
|
|
|
|
|
|
ereport(FATAL,
|
|
|
|
|
(errcode(ERRCODE_ADMIN_SHUTDOWN),
|
|
|
|
|
errmsg("terminating background worker \"%s\" due to administrator command",
|
|
|
|
|
MyBgworkerEntry->bgw_name)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Standard SIGUSR1 handler for unconnected workers
|
|
|
|
|
*
|
|
|
|
|
* Here, we want to make sure an unconnected worker will at least heed
|
|
|
|
|
* latch activity.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
bgworker_sigusr1_handler(SIGNAL_ARGS)
|
|
|
|
|
{
|
|
|
|
|
int save_errno = errno;
|
|
|
|
|
|
|
|
|
|
latch_sigusr1_handler();
|
|
|
|
|
|
|
|
|
|
errno = save_errno;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Start a new background worker
|
|
|
|
|
*
|
|
|
|
|
* This is the main entry point for background worker, to be called from
|
|
|
|
|
* postmaster.
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
StartBackgroundWorker(void)
|
|
|
|
|
{
|
|
|
|
|
sigjmp_buf local_sigjmp_buf;
|
|
|
|
|
char buf[MAXPGPATH];
|
|
|
|
|
BackgroundWorker *worker = MyBgworkerEntry;
|
|
|
|
|
bgworker_main_type entrypt;
|
|
|
|
|
|
|
|
|
|
if (worker == NULL)
|
|
|
|
|
elog(FATAL, "unable to find bgworker entry");
|
|
|
|
|
|
|
|
|
|
/* we are a postmaster subprocess now */
|
|
|
|
|
IsUnderPostmaster = true;
|
|
|
|
|
IsBackgroundWorker = true;
|
|
|
|
|
|
|
|
|
|
/* reset MyProcPid */
|
|
|
|
|
MyProcPid = getpid();
|
|
|
|
|
|
|
|
|
|
/* record Start Time for logging */
|
|
|
|
|
MyStartTime = time(NULL);
|
|
|
|
|
|
|
|
|
|
/* Identify myself via ps */
|
|
|
|
|
snprintf(buf, MAXPGPATH, "bgworker: %s", worker->bgw_name);
|
|
|
|
|
init_ps_display(buf, "", "", "");
|
|
|
|
|
|
|
|
|
|
SetProcessingMode(InitProcessing);
|
|
|
|
|
|
|
|
|
|
/* Apply PostAuthDelay */
|
|
|
|
|
if (PostAuthDelay > 0)
|
|
|
|
|
pg_usleep(PostAuthDelay * 1000000L);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If possible, make this process a group leader, so that the postmaster
|
|
|
|
|
* can signal any child processes too.
|
|
|
|
|
*/
|
|
|
|
|
#ifdef HAVE_SETSID
|
|
|
|
|
if (setsid() < 0)
|
|
|
|
|
elog(FATAL, "setsid() failed: %m");
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Set up signal handlers.
|
|
|
|
|
*/
|
|
|
|
|
if (worker->bgw_flags & BGWORKER_BACKEND_DATABASE_CONNECTION)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* SIGINT is used to signal canceling the current action
|
|
|
|
|
*/
|
|
|
|
|
pqsignal(SIGINT, StatementCancelHandler);
|
|
|
|
|
pqsignal(SIGUSR1, procsignal_sigusr1_handler);
|
|
|
|
|
pqsignal(SIGFPE, FloatExceptionHandler);
|
|
|
|
|
|
|
|
|
|
/* XXX Any other handlers needed here? */
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
pqsignal(SIGINT, SIG_IGN);
|
|
|
|
|
pqsignal(SIGUSR1, bgworker_sigusr1_handler);
|
|
|
|
|
pqsignal(SIGFPE, SIG_IGN);
|
|
|
|
|
}
|
|
|
|
|
pqsignal(SIGTERM, bgworker_die);
|
|
|
|
|
pqsignal(SIGHUP, SIG_IGN);
|
|
|
|
|
|
|
|
|
|
pqsignal(SIGQUIT, bgworker_quickdie);
|
|
|
|
|
InitializeTimeouts(); /* establishes SIGALRM handler */
|
|
|
|
|
|
|
|
|
|
pqsignal(SIGPIPE, SIG_IGN);
|
|
|
|
|
pqsignal(SIGUSR2, SIG_IGN);
|
|
|
|
|
pqsignal(SIGCHLD, SIG_DFL);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If an exception is encountered, processing resumes here.
|
|
|
|
|
*
|
|
|
|
|
* See notes in postgres.c about the design of this coding.
|
|
|
|
|
*/
|
|
|
|
|
if (sigsetjmp(local_sigjmp_buf, 1) != 0)
|
|
|
|
|
{
|
|
|
|
|
/* Since not using PG_TRY, must reset error stack by hand */
|
|
|
|
|
error_context_stack = NULL;
|
|
|
|
|
|
|
|
|
|
/* Prevent interrupts while cleaning up */
|
|
|
|
|
HOLD_INTERRUPTS();
|
|
|
|
|
|
|
|
|
|
/* Report the error to the server log */
|
|
|
|
|
EmitErrorReport();
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Do we need more cleanup here? For shmem-connected bgworkers, we
|
|
|
|
|
* will call InitProcess below, which will install ProcKill as exit
|
|
|
|
|
* callback. That will take care of releasing locks, etc.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/* and go away */
|
|
|
|
|
proc_exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* We can now handle ereport(ERROR) */
|
|
|
|
|
PG_exception_stack = &local_sigjmp_buf;
|
|
|
|
|
|
|
|
|
|
/* Early initialization */
|
|
|
|
|
BaseInit();
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If necessary, create a per-backend PGPROC struct in shared memory,
|
|
|
|
|
* except in the EXEC_BACKEND case where this was done in
|
|
|
|
|
* SubPostmasterMain. We must do this before we can use LWLocks (and in
|
|
|
|
|
* the EXEC_BACKEND case we already had to do some stuff with LWLocks).
|
|
|
|
|
*/
|
|
|
|
|
#ifndef EXEC_BACKEND
|
|
|
|
|
if (worker->bgw_flags & BGWORKER_SHMEM_ACCESS)
|
|
|
|
|
InitProcess();
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If bgw_main is set, we use that value as the initial entrypoint.
|
|
|
|
|
* However, if the library containing the entrypoint wasn't loaded at
|
|
|
|
|
* postmaster startup time, passing it as a direct function pointer is
|
|
|
|
|
* not possible. To work around that, we allow callers for whom a
|
|
|
|
|
* function pointer is not available to pass a library name (which will
|
|
|
|
|
* be loaded, if necessary) and a function name (which will be looked up
|
|
|
|
|
* in the named library).
|
|
|
|
|
*/
|
|
|
|
|
if (worker->bgw_main != NULL)
|
|
|
|
|
entrypt = worker->bgw_main;
|
|
|
|
|
else
|
|
|
|
|
entrypt = (bgworker_main_type)
|
|
|
|
|
load_external_function(worker->bgw_library_name,
|
|
|
|
|
worker->bgw_function_name,
|
|
|
|
|
true, NULL);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Note that in normal processes, we would call InitPostgres here. For a
|
|
|
|
|
* worker, however, we don't know what database to connect to, yet; so we
|
|
|
|
|
* need to wait until the user code does it via
|
|
|
|
|
* BackgroundWorkerInitializeConnection().
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Now invoke the user-defined worker code
|
|
|
|
|
*/
|
|
|
|
|
entrypt(worker->bgw_main_arg);
|
|
|
|
|
|
|
|
|
|
/* ... and if it returns, we're done */
|
|
|
|
|
proc_exit(0);
|
|
|
|
|
}
|
|
|
|
|
|
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.
13 years ago
|
|
|
/*
|
|
|
|
|
* Register a new background worker while processing shared_preload_libraries.
|
|
|
|
|
*
|
|
|
|
|
* This can only be called in the _PG_init function of a module library
|
|
|
|
|
* that's loaded by shared_preload_libraries; otherwise it has no effect.
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
RegisterBackgroundWorker(BackgroundWorker *worker)
|
|
|
|
|
{
|
|
|
|
|
RegisteredBgWorker *rw;
|
|
|
|
|
static int numworkers = 0;
|
|
|
|
|
|
|
|
|
|
if (!IsUnderPostmaster)
|
|
|
|
|
ereport(LOG,
|
|
|
|
|
(errmsg("registering background worker \"%s\"", worker->bgw_name)));
|
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.
13 years ago
|
|
|
|
|
|
|
|
if (!process_shared_preload_libraries_in_progress)
|
|
|
|
|
{
|
|
|
|
|
if (!IsUnderPostmaster)
|
|
|
|
|
ereport(LOG,
|
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
|
|
|
|
errmsg("background worker \"%s\": must be registered in shared_preload_libraries",
|
|
|
|
|
worker->bgw_name)));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!SanityCheckBackgroundWorker(worker, LOG))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Enforce maximum number of workers. Note this is overly restrictive: we
|
|
|
|
|
* could allow more non-shmem-connected workers, because these don't count
|
|
|
|
|
* towards the MAX_BACKENDS limit elsewhere. For now, it doesn't seem
|
|
|
|
|
* important to relax this restriction.
|
|
|
|
|
*/
|
|
|
|
|
if (++numworkers > max_worker_processes)
|
|
|
|
|
{
|
|
|
|
|
ereport(LOG,
|
|
|
|
|
(errcode(ERRCODE_CONFIGURATION_LIMIT_EXCEEDED),
|
|
|
|
|
errmsg("too many background workers"),
|
|
|
|
|
errdetail_plural("Up to %d background worker can be registered with the current settings.",
|
|
|
|
|
"Up to %d background workers can be registered with the current settings.",
|
|
|
|
|
max_worker_processes,
|
|
|
|
|
max_worker_processes),
|
|
|
|
|
errhint("Consider increasing the configuration parameter \"max_worker_processes\".")));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Copy the registration data into the registered workers list.
|
|
|
|
|
*/
|
|
|
|
|
rw = malloc(sizeof(RegisteredBgWorker));
|
|
|
|
|
if (rw == NULL)
|
|
|
|
|
{
|
|
|
|
|
ereport(LOG,
|
|
|
|
|
(errcode(ERRCODE_OUT_OF_MEMORY),
|
|
|
|
|
errmsg("out of memory")));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rw->rw_worker = *worker;
|
|
|
|
|
rw->rw_backend = NULL;
|
|
|
|
|
rw->rw_pid = 0;
|
|
|
|
|
rw->rw_child_slot = 0;
|
|
|
|
|
rw->rw_crashed_at = 0;
|
|
|
|
|
|
|
|
|
|
slist_push_head(&BackgroundWorkerList, &rw->rw_lnode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Register a new background worker from a regular backend.
|
|
|
|
|
*
|
|
|
|
|
* Returns true on success and false on failure. Failure typically indicates
|
|
|
|
|
* that no background worker slots are currently available.
|
|
|
|
|
*/
|
|
|
|
|
bool
|
|
|
|
|
RegisterDynamicBackgroundWorker(BackgroundWorker *worker)
|
|
|
|
|
{
|
|
|
|
|
int slotno;
|
|
|
|
|
bool success = false;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* We can't register dynamic background workers from the postmaster.
|
|
|
|
|
* If this is a standalone backend, we're the only process and can't
|
|
|
|
|
* start any more. In a multi-process environement, it might be
|
|
|
|
|
* theoretically possible, but we don't currently support it due to
|
|
|
|
|
* locking considerations; see comments on the BackgroundWorkerSlot
|
|
|
|
|
* data structure.
|
|
|
|
|
*/
|
|
|
|
|
if (!IsUnderPostmaster)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (!SanityCheckBackgroundWorker(worker, ERROR))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
LWLockAcquire(BackgroundWorkerLock, LW_EXCLUSIVE);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Look for an unused slot. If we find one, grab it.
|
|
|
|
|
*/
|
|
|
|
|
for (slotno = 0; slotno < BackgroundWorkerData->total_slots; ++slotno)
|
|
|
|
|
{
|
|
|
|
|
BackgroundWorkerSlot *slot = &BackgroundWorkerData->slot[slotno];
|
|
|
|
|
|
|
|
|
|
if (!slot->in_use)
|
|
|
|
|
{
|
|
|
|
|
memcpy(&slot->worker, worker, sizeof(BackgroundWorker));
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Make sure postmaster doesn't see the slot as in use before
|
|
|
|
|
* it sees the new contents.
|
|
|
|
|
*/
|
|
|
|
|
pg_write_barrier();
|
|
|
|
|
|
|
|
|
|
slot->in_use = true;
|
|
|
|
|
success = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LWLockRelease(BackgroundWorkerLock);
|
|
|
|
|
|
|
|
|
|
/* If we found a slot, tell the postmaster to notice the change. */
|
|
|
|
|
if (success)
|
|
|
|
|
SendPostmasterSignal(PMSIGNAL_BACKGROUND_WORKER_CHANGE);
|
|
|
|
|
|
|
|
|
|
return success;
|
|
|
|
|
}
|