Skip to content

Commit 916b8ae

Browse files
committed
Don't enter parallel mode when holding interrupts.
Doing so caused the leader to hang in wait_event=ParallelFinish, which required an immediate shutdown to resolve. Back-patch to v12 (all supported versions). Francesco Degrassi Discussion: https://postgr.es/m/CAC-SaSzHUKT=vZJ8MPxYdC_URPfax+yoA1hKTcF4ROz_Q6z0_Q@mail.gmail.com
1 parent a01dbdb commit 916b8ae

File tree

3 files changed

+61
-0
lines changed

3 files changed

+61
-0
lines changed

src/backend/optimizer/plan/planner.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,11 @@ standard_planner(Query *parse, const char *query_string, int cursorOptions,
332332
* if we want to allow parallel inserts in general; updates and deletes
333333
* have additional problems especially around combo CIDs.)
334334
*
335+
* We don't try to use parallel mode unless interruptible. The leader
336+
* expects ProcessInterrupts() calls to reach HandleParallelMessages().
337+
* Even if we called HandleParallelMessages() another way, starting a
338+
* parallel worker is too delay-prone to be prudent when uncancellable.
339+
*
335340
* For now, we don't try to use parallel mode if we're running inside a
336341
* parallel worker. We might eventually be able to relax this
337342
* restriction, but for now it seems best not to have parallel workers
@@ -342,6 +347,7 @@ standard_planner(Query *parse, const char *query_string, int cursorOptions,
342347
parse->commandType == CMD_SELECT &&
343348
!parse->hasModifyingCTE &&
344349
max_parallel_workers_per_gather > 0 &&
350+
INTERRUPTS_CAN_BE_PROCESSED() &&
345351
!IsParallelWorker())
346352
{
347353
/* all the cheap tests pass, so scan the query tree */

src/test/regress/expected/select_parallel.out

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1254,3 +1254,27 @@ reset force_parallel_mode;
12541254
drop function set_and_report_role();
12551255
drop function set_role_and_error(int);
12561256
drop role regress_parallel_worker;
1257+
-- don't freeze in ParallelFinish while holding an LWLock
1258+
BEGIN;
1259+
CREATE FUNCTION my_cmp (int4, int4)
1260+
RETURNS int LANGUAGE sql AS
1261+
$$
1262+
SELECT
1263+
CASE WHEN $1 < $2 THEN -1
1264+
WHEN $1 > $2 THEN 1
1265+
ELSE 0
1266+
END;
1267+
$$;
1268+
CREATE TABLE parallel_hang (i int4);
1269+
INSERT INTO parallel_hang
1270+
(SELECT * FROM generate_series(1, 400) gs);
1271+
CREATE OPERATOR CLASS int4_custom_ops FOR TYPE int4 USING btree AS
1272+
OPERATOR 1 < (int4, int4), OPERATOR 2 <= (int4, int4),
1273+
OPERATOR 3 = (int4, int4), OPERATOR 4 >= (int4, int4),
1274+
OPERATOR 5 > (int4, int4), FUNCTION 1 my_cmp(int4, int4);
1275+
CREATE UNIQUE INDEX parallel_hang_idx
1276+
ON parallel_hang
1277+
USING btree (i int4_custom_ops);
1278+
SET force_parallel_mode = on;
1279+
DELETE FROM parallel_hang WHERE 380 <= i AND i <= 420;
1280+
ROLLBACK;

src/test/regress/sql/select_parallel.sql

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,3 +487,34 @@ reset force_parallel_mode;
487487
drop function set_and_report_role();
488488
drop function set_role_and_error(int);
489489
drop role regress_parallel_worker;
490+
491+
-- don't freeze in ParallelFinish while holding an LWLock
492+
BEGIN;
493+
494+
CREATE FUNCTION my_cmp (int4, int4)
495+
RETURNS int LANGUAGE sql AS
496+
$$
497+
SELECT
498+
CASE WHEN $1 < $2 THEN -1
499+
WHEN $1 > $2 THEN 1
500+
ELSE 0
501+
END;
502+
$$;
503+
504+
CREATE TABLE parallel_hang (i int4);
505+
INSERT INTO parallel_hang
506+
(SELECT * FROM generate_series(1, 400) gs);
507+
508+
CREATE OPERATOR CLASS int4_custom_ops FOR TYPE int4 USING btree AS
509+
OPERATOR 1 < (int4, int4), OPERATOR 2 <= (int4, int4),
510+
OPERATOR 3 = (int4, int4), OPERATOR 4 >= (int4, int4),
511+
OPERATOR 5 > (int4, int4), FUNCTION 1 my_cmp(int4, int4);
512+
513+
CREATE UNIQUE INDEX parallel_hang_idx
514+
ON parallel_hang
515+
USING btree (i int4_custom_ops);
516+
517+
SET force_parallel_mode = on;
518+
DELETE FROM parallel_hang WHERE 380 <= i AND i <= 420;
519+
520+
ROLLBACK;

0 commit comments

Comments
 (0)