diff options
Diffstat (limited to 'src/backend')
| -rw-r--r-- | src/backend/lib/ilist.c | 2 | ||||
| -rw-r--r-- | src/backend/postmaster/bgworker.c | 15 | ||||
| -rw-r--r-- | src/backend/postmaster/pgstat.c | 7 | ||||
| -rw-r--r-- | src/backend/postmaster/postmaster.c | 4 |
4 files changed, 20 insertions, 8 deletions
diff --git a/src/backend/lib/ilist.c b/src/backend/lib/ilist.c index 957a118122..eb23fa1c68 100644 --- a/src/backend/lib/ilist.c +++ b/src/backend/lib/ilist.c @@ -28,7 +28,7 @@ * * It is not allowed to delete a 'node' which is is not in the list 'head' * - * Caution: this is O(n) + * Caution: this is O(n); consider using slist_delete_current() instead. */ void slist_delete(slist_head *head, slist_node *node) 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; } |
