fix_parallel_worker_startup_failures_v2.patch
application/octet-stream
Filename: fix_parallel_worker_startup_failures_v2.patch
Type: application/octet-stream
Part: 0
Patch
Format: unified
Series: patch v2
| File | + | − |
|---|---|---|
| src/backend/access/transam/parallel.c | 36 | 2 |
diff --git a/src/backend/access/transam/parallel.c b/src/backend/access/transam/parallel.c
index d3431a7..5c7b794 100644
--- a/src/backend/access/transam/parallel.c
+++ b/src/backend/access/transam/parallel.c
@@ -538,8 +538,16 @@ LaunchParallelWorkers(ParallelContext *pcxt)
void
WaitForParallelWorkersToFinish(ParallelContext *pcxt)
{
+ bool *alive_workers;
+ bool *dead_workers;
+ int nworkers = pcxt->nworkers_launched;
+
+ alive_workers = (bool *) palloc0(nworkers * sizeof(bool));
+ dead_workers = (bool *) palloc0(nworkers * sizeof(bool));
+
for (;;)
{
+ BgwHandleStatus status;
bool anyone_alive = false;
int i;
@@ -550,9 +558,31 @@ WaitForParallelWorkersToFinish(ParallelContext *pcxt)
*/
CHECK_FOR_INTERRUPTS();
- for (i = 0; i < pcxt->nworkers_launched; ++i)
+ for (i = 0; i < pcxt->nworkers; ++i)
{
- if (pcxt->worker[i].error_mqh != NULL)
+ pid_t pid;
+
+ if (pcxt->worker == NULL || pcxt->worker[i].bgwhandle == NULL)
+ continue;
+
+ /*
+ * Check for unexpected worker death. This will ensure that if
+ * the postmaster failed to start the worker or the worker errored
+ * out before attaching to error queue, then we don't wait for it
+ * indefinitely.
+ */
+ if (!alive_workers[i])
+ {
+ status = GetBackgroundWorkerPid(pcxt->worker[i].bgwhandle,
+ &pid);
+ if (status == BGWH_STOPPED)
+ dead_workers[i] = true;
+ if (status != BGWH_NOT_YET_STARTED)
+ alive_workers[i] = true;
+ }
+
+ if (pcxt->worker[i].error_mqh != NULL &&
+ !dead_workers[i])
{
anyone_alive = true;
break;
@@ -567,6 +597,10 @@ WaitForParallelWorkersToFinish(ParallelContext *pcxt)
ResetLatch(MyLatch);
}
+ /* be tidy */
+ pfree(alive_workers);
+ pfree(dead_workers);
+
if (pcxt->toc != NULL)
{
FixedParallelState *fps;