summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/postmaster/bgworker.c33
-rw-r--r--src/backend/postmaster/postmaster.c6
-rw-r--r--src/include/postmaster/bgworker_internals.h1
3 files changed, 37 insertions, 3 deletions
diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c
index cd99b0b3927..42760b92bb1 100644
--- a/src/backend/postmaster/bgworker.c
+++ b/src/backend/postmaster/bgworker.c
@@ -430,6 +430,39 @@ ReportBackgroundWorkerPID(RegisteredBgWorker *rw)
}
/*
+ * Report that the PID of a background worker is now zero because a
+ * previously-running background worker has exited.
+ *
+ * This function should only be called from the postmaster.
+ */
+void
+ReportBackgroundWorkerExit(slist_mutable_iter *cur)
+{
+ RegisteredBgWorker *rw;
+ BackgroundWorkerSlot *slot;
+
+ rw = slist_container(RegisteredBgWorker, rw_lnode, cur->cur);
+
+ Assert(rw->rw_shmem_slot < max_worker_processes);
+ slot = &BackgroundWorkerData->slot[rw->rw_shmem_slot];
+ slot->pid = rw->rw_pid;
+
+ /*
+ * If this worker is slated for deregistration, do that before notifying
+ * the process which started it. Otherwise, if that process tries to
+ * reuse the slot immediately, it might not be available yet. In theory
+ * that could happen anyway if the process checks slot->pid at just the
+ * wrong moment, but this makes the window narrower.
+ */
+ if (rw->rw_terminate ||
+ rw->rw_worker.bgw_restart_time == BGW_NEVER_RESTART)
+ ForgetBackgroundWorker(cur);
+
+ if (rw->rw_worker.bgw_notify_pid != 0)
+ kill(rw->rw_worker.bgw_notify_pid, SIGUSR1);
+}
+
+/*
* Cancel SIGUSR1 notifications for a PID belonging to an exiting backend.
*
* This function should only be called from the postmaster.
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 271c4920002..2cf17ac42e0 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -3050,9 +3050,9 @@ CleanupBackgroundWorker(int pid,
int exitstatus) /* child's exit status */
{
char namebuf[MAXPGPATH];
- slist_iter iter;
+ slist_mutable_iter iter;
- slist_foreach(iter, &BackgroundWorkerList)
+ slist_foreach_modify(iter, &BackgroundWorkerList)
{
RegisteredBgWorker *rw;
@@ -3126,7 +3126,7 @@ CleanupBackgroundWorker(int pid,
rw->rw_backend = NULL;
rw->rw_pid = 0;
rw->rw_child_slot = 0;
- ReportBackgroundWorkerPID(rw); /* report child death */
+ ReportBackgroundWorkerExit(&iter); /* report child death */
LogChildExit(EXIT_STATUS_0(exitstatus) ? DEBUG1 : LOG,
namebuf, pid, exitstatus);
diff --git a/src/include/postmaster/bgworker_internals.h b/src/include/postmaster/bgworker_internals.h
index 4c94b815b12..9a2de4f4d04 100644
--- a/src/include/postmaster/bgworker_internals.h
+++ b/src/include/postmaster/bgworker_internals.h
@@ -42,6 +42,7 @@ extern void BackgroundWorkerShmemInit(void);
extern void BackgroundWorkerStateChange(void);
extern void ForgetBackgroundWorker(slist_mutable_iter *cur);
extern void ReportBackgroundWorkerPID(RegisteredBgWorker *);
+extern void ReportBackgroundWorkerExit(slist_mutable_iter *cur);
extern void BackgroundWorkerStopNotifications(pid_t pid);
extern void ResetBackgroundWorkerCrashTimes(void);