PostgreSQL can be extended to run user-supplied code in separate processes.
Such processes are started, stopped and monitored by <command>postgres</command>,
which permits them to have a lifetime closely linked to the server's status.
- These processes have the option to attach to <productname>PostgreSQL</productname>'s
- shared memory area and to connect to databases internally; they can also run
+ These processes are attached to <productname>PostgreSQL</productname>'s
+ shared memory area and have the option to connect to databases internally; they can also run
multiple transactions serially, just like a regular client-connected server
process. Also, by linking to <application>libpq</application> they can connect to the
server and behave like a regular client application.
<listitem>
<para>
<indexterm><primary>BGWORKER_SHMEM_ACCESS</primary></indexterm>
- Requests shared memory access. Workers without shared memory access
- cannot access any of <productname>PostgreSQL's</productname> shared
- data structures, such as heavyweight or lightweight locks, shared
- buffers, or any custom data structures which the worker itself may
- wish to create and use.
+ Requests shared memory access. This flag is required.
</para>
</listitem>
</varlistentry>
SanityCheckBackgroundWorker(BackgroundWorker *worker, int elevel)
{
/* sanity check for flags */
- if (worker->bgw_flags & BGWORKER_BACKEND_DATABASE_CONNECTION)
+
+ /*
+ * We used to support workers not connected to shared memory, but don't
+ * anymore. Thus this is a required flag now. We're not removing the flag
+ * for compatibility reasons and because the flag still provides some
+ * signal when reading code.
+ */
+ if (!(worker->bgw_flags & BGWORKER_SHMEM_ACCESS))
{
- 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;
- }
+ ereport(elevel,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("background worker \"%s\": background worker without shared memory access are not supported",
+ worker->bgw_name)));
+ return false;
+ }
+ if (worker->bgw_flags & BGWORKER_BACKEND_DATABASE_CONNECTION)
+ {
if (worker->bgw_start_time == BgWorkerStart_PostmasterStart)
{
ereport(elevel,
MyBackendType = B_BG_WORKER;
init_ps_display(worker->bgw_name);
- /*
- * If we're not supposed to have shared memory access, then detach from
- * shared memory. If we didn't request shared memory access, the
- * postmaster won't force a cluster-wide restart if we exit unexpectedly,
- * so we'd better make sure that we don't mess anything up that would
- * require that sort of cleanup.
- */
- if ((worker->bgw_flags & BGWORKER_SHMEM_ACCESS) == 0)
- {
- ShutdownLatchSupport();
- dsm_detach_all();
- PGSharedMemoryDetach();
- }
-
SetProcessingMode(InitProcessing);
/* Apply PostAuthDelay */
PG_exception_stack = &local_sigjmp_buf;
/*
- * If the background worker request shared memory access, set that up now;
- * else, detach all shared memory segments.
+ * 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).
*/
- if (worker->bgw_flags & BGWORKER_SHMEM_ACCESS)
- {
- /*
- * 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
- InitProcess();
+ InitProcess();
#endif
- /*
- * Early initialization. Some of this could be useful even for
- * background workers that aren't using shared memory, but they can
- * call the individual startup routines for those subsystems if
- * needed.
- */
- BaseInit();
- }
+ /*
+ * Early initialization.
+ */
+ BaseInit();
/*
* Look up the entry point function, loading its library if necessary.
}
/*
- * Additionally, for shared-memory-connected workers, just like a
- * backend, any exit status other than 0 or 1 is considered a crash
- * and causes a system-wide restart.
+ * Additionally, just like a backend, any exit status other than 0 or
+ * 1 is considered a crash and causes a system-wide restart.
*/
- if ((rw->rw_worker.bgw_flags & BGWORKER_SHMEM_ACCESS) != 0)
+ if (!EXIT_STATUS_0(exitstatus) && !EXIT_STATUS_1(exitstatus))
{
- if (!EXIT_STATUS_0(exitstatus) && !EXIT_STATUS_1(exitstatus))
- {
- HandleChildCrash(pid, exitstatus, namebuf);
- return true;
- }
+ HandleChildCrash(pid, exitstatus, namebuf);
+ return true;
}
/*
- * We must release the postmaster child slot whether this worker is
- * connected to shared memory or not, but we only treat it as a crash
- * if it is in fact connected.
+ * We must release the postmaster child slot. If the worker failed to
+ * do so, it did not clean up after itself, requiring a crash-restart
+ * cycle.
*/
- if (!ReleasePostmasterChildSlot(rw->rw_child_slot) &&
- (rw->rw_worker.bgw_flags & BGWORKER_SHMEM_ACCESS) != 0)
+ if (!ReleasePostmasterChildSlot(rw->rw_child_slot))
{
HandleChildCrash(pid, exitstatus, namebuf);
return true;