Skip to content

Commit 4853630

Browse files
committed
Allow parallel workers to cope with a newly-created session user ID.
Parallel workers failed after a sequence like BEGIN; CREATE USER foo; SET SESSION AUTHORIZATION foo; because check_session_authorization could not see the uncommitted pg_authid row for "foo". This is because we ran RestoreGUCState() in a separate transaction using an ordinary just-created snapshot. The same disease afflicts any other GUC that requires catalog lookups and isn't forgiving about the lookups failing. To fix, postpone RestoreGUCState() into the worker's main transaction after we've set up a snapshot duplicating the leader's. This affects check_transaction_isolation and check_transaction_deferrable, which think they should only run during transaction start. Make them act like check_transaction_read_only, which already knows it should silently accept the value when InitializingParallelWorker. Per bug #18545 from Andrey Rachitskiy. Back-patch to all supported branches, because this has been wrong for awhile. Discussion: https://postgr.es/m/18545-feba138862f19aaa@postgresql.org
1 parent 27146e7 commit 4853630

File tree

4 files changed

+43
-6
lines changed

4 files changed

+43
-6
lines changed

src/backend/access/transam/parallel.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1402,10 +1402,6 @@ ParallelWorkerMain(Datum main_arg)
14021402
libraryspace = shm_toc_lookup(toc, PARALLEL_KEY_LIBRARY, false);
14031403
StartTransactionCommand();
14041404
RestoreLibraryState(libraryspace);
1405-
1406-
/* Restore GUC values from launching backend. */
1407-
gucspace = shm_toc_lookup(toc, PARALLEL_KEY_GUC, false);
1408-
RestoreGUCState(gucspace);
14091405
CommitTransactionCommand();
14101406

14111407
/* Crank up a transaction state appropriate to a parallel worker. */
@@ -1447,6 +1443,14 @@ ParallelWorkerMain(Datum main_arg)
14471443
*/
14481444
InvalidateSystemCaches();
14491445

1446+
/*
1447+
* Restore GUC values from launching backend. We can't do this earlier,
1448+
* because GUC check hooks that do catalog lookups need to see the same
1449+
* database state as the leader.
1450+
*/
1451+
gucspace = shm_toc_lookup(toc, PARALLEL_KEY_GUC, false);
1452+
RestoreGUCState(gucspace);
1453+
14501454
/*
14511455
* Restore current role id. Skip verifying whether session user is
14521456
* allowed to become this role and blindly restore the leader's state for

src/backend/commands/variable.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -519,14 +519,16 @@ check_transaction_read_only(bool *newval, void **extra, GucSource source)
519519
* We allow idempotent changes at any time, but otherwise this can only be
520520
* changed in a toplevel transaction that has not yet taken a snapshot.
521521
*
522-
* As in check_transaction_read_only, allow it if not inside a transaction.
522+
* As in check_transaction_read_only, allow it if not inside a transaction,
523+
* or if restoring state in a parallel worker.
523524
*/
524525
bool
525526
check_XactIsoLevel(int *newval, void **extra, GucSource source)
526527
{
527528
int newXactIsoLevel = *newval;
528529

529-
if (newXactIsoLevel != XactIsoLevel && IsTransactionState())
530+
if (newXactIsoLevel != XactIsoLevel &&
531+
IsTransactionState() && !InitializingParallelWorker)
530532
{
531533
if (FirstSnapshotSet)
532534
{
@@ -561,6 +563,10 @@ check_XactIsoLevel(int *newval, void **extra, GucSource source)
561563
bool
562564
check_transaction_deferrable(bool *newval, void **extra, GucSource source)
563565
{
566+
/* Just accept the value when restoring state in a parallel worker */
567+
if (InitializingParallelWorker)
568+
return true;
569+
564570
if (IsSubTransaction())
565571
{
566572
GUC_check_errcode(ERRCODE_ACTIVE_SQL_TRANSACTION);

src/test/regress/expected/select_parallel.out

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1219,3 +1219,21 @@ SELECT 1 FROM tenk1_vw_sec
12191219
(9 rows)
12201220

12211221
rollback;
1222+
-- test that a newly-created session role propagates to workers.
1223+
begin;
1224+
create role regress_parallel_worker;
1225+
set session authorization regress_parallel_worker;
1226+
select current_setting('session_authorization');
1227+
current_setting
1228+
-------------------------
1229+
regress_parallel_worker
1230+
(1 row)
1231+
1232+
set force_parallel_mode = 1;
1233+
select current_setting('session_authorization');
1234+
current_setting
1235+
-------------------------
1236+
regress_parallel_worker
1237+
(1 row)
1238+
1239+
rollback;

src/test/regress/sql/select_parallel.sql

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,3 +462,12 @@ SELECT 1 FROM tenk1_vw_sec
462462
WHERE (SELECT sum(f1) FROM int4_tbl WHERE f1 < unique1) < 100;
463463

464464
rollback;
465+
466+
-- test that a newly-created session role propagates to workers.
467+
begin;
468+
create role regress_parallel_worker;
469+
set session authorization regress_parallel_worker;
470+
select current_setting('session_authorization');
471+
set force_parallel_mode = 1;
472+
select current_setting('session_authorization');
473+
rollback;

0 commit comments

Comments
 (0)