summaryrefslogtreecommitdiff
path: root/src/backend/postmaster
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/postmaster')
-rw-r--r--src/backend/postmaster/bgworker.c15
-rw-r--r--src/backend/postmaster/pgstat.c7
-rw-r--r--src/backend/postmaster/postmaster.c4
3 files changed, 19 insertions, 7 deletions
diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c
index ada24e905e..f807c9cfa1 100644
--- a/src/backend/postmaster/bgworker.c
+++ b/src/backend/postmaster/bgworker.c
@@ -267,15 +267,20 @@ BackgroundWorkerStateChange(void)
/*
* Forget about a background worker that's no longer needed.
*
- * At present, this only happens when a background worker marked
- * BGW_NEVER_RESTART exits. This function should only be invoked in
- * the postmaster.
+ * 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.
*/
void
-ForgetBackgroundWorker(RegisteredBgWorker *rw)
+ForgetBackgroundWorker(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->in_use = false;
@@ -284,7 +289,7 @@ ForgetBackgroundWorker(RegisteredBgWorker *rw)
(errmsg("unregistering background worker: %s",
rw->rw_worker.bgw_name)));
- slist_delete(&BackgroundWorkerList, &rw->rw_lnode);
+ slist_delete_current(cur);
free(rw);
}
diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index e539bac0c1..a52377fc9d 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -3602,6 +3602,13 @@ pgstat_write_statsfiles(bool permanent, bool allDbs)
{
slist_mutable_iter iter;
+ /*
+ * Strictly speaking we should do slist_delete_current() before
+ * freeing each request struct. We skip that and instead
+ * re-initialize the list header at the end. Nonetheless, we must use
+ * slist_foreach_modify, not just slist_foreach, since we will free
+ * the node's storage before advancing.
+ */
slist_foreach_modify(iter, &last_statrequests)
{
DBWriteRequest *req;
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 7894217ed5..e6d750d4d3 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -1452,7 +1452,7 @@ DetermineSleepTime(struct timeval * timeout)
if (rw->rw_worker.bgw_restart_time == BGW_NEVER_RESTART)
{
- ForgetBackgroundWorker(rw);
+ ForgetBackgroundWorker(&siter);
continue;
}
@@ -5641,7 +5641,7 @@ StartOneBackgroundWorker(void)
{
if (rw->rw_worker.bgw_restart_time == BGW_NEVER_RESTART)
{
- ForgetBackgroundWorker(rw);
+ ForgetBackgroundWorker(&iter);
continue;
}