Skip to content

Commit 31ed3cf

Browse files
committed
Process session_preload_libraries within InitPostgres's transaction.
Previously we did this after InitPostgres, at a somewhat randomly chosen place within PostgresMain. However, since commit a0ffa88 doing this outside a transaction can cause a crash, if we need to check permissions while replacing a placeholder GUC. (Besides which, a preloaded library could itself want to do database access within _PG_init.) To avoid needing an additional transaction start/end in every session, move the process_session_preload_libraries call to within InitPostgres's transaction. That requires teaching the code not to call it when InitPostgres is called from somewhere other than PostgresMain, since we don't want session_preload_libraries to affect background workers. The most future-proof solution here seems to be to add an additional flag parameter to InitPostgres; fortunately, we're not yet very worried about API stability for v15. Doing this also exposed the fact that we're currently honoring session_preload_libraries in walsenders, even those not connected to any database. This seems, at minimum, a POLA violation: walsenders are not interactive sessions. Let's stop doing that. (All these comments also apply to local_preload_libraries, of course.) Per report from Gurjeet Singh (thanks also to Nathan Bossart and Kyotaro Horiguchi for review). Backpatch to v15 where a0ffa88 came in. Discussion: https://postgr.es/m/CABwTF4VEpwTHhRQ+q5MiC5ucngN-whN-PdcKeufX7eLSoAfbZA@mail.gmail.com
1 parent 19f8232 commit 31ed3cf

File tree

6 files changed

+64
-25
lines changed

6 files changed

+64
-25
lines changed

src/backend/bootstrap/bootstrap.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ BootstrapModeMain(int argc, char *argv[], bool check_only)
355355
if (pg_link_canary_is_frontend())
356356
elog(ERROR, "backend is incorrectly linked to frontend functions");
357357

358-
InitPostgres(NULL, InvalidOid, NULL, InvalidOid, NULL, false);
358+
InitPostgres(NULL, InvalidOid, NULL, InvalidOid, false, false, NULL);
359359

360360
/* Initialize stuff for bootstrap-file processing */
361361
for (i = 0; i < MAXATTR; i++)

src/backend/postmaster/autovacuum.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,7 @@ AutoVacLauncherMain(int argc, char *argv[])
475475
/* Early initialization */
476476
BaseInit();
477477

478-
InitPostgres(NULL, InvalidOid, NULL, InvalidOid, NULL, false);
478+
InitPostgres(NULL, InvalidOid, NULL, InvalidOid, false, false, NULL);
479479

480480
SetProcessingMode(NormalProcessing);
481481

@@ -1694,12 +1694,13 @@ AutoVacWorkerMain(int argc, char *argv[])
16941694
pgstat_report_autovac(dbid);
16951695

16961696
/*
1697-
* Connect to the selected database
1697+
* Connect to the selected database, specifying no particular user
16981698
*
16991699
* Note: if we have selected a just-deleted database (due to using
17001700
* stale stats info), we'll fail and exit here.
17011701
*/
1702-
InitPostgres(NULL, dbid, NULL, InvalidOid, dbname, false);
1702+
InitPostgres(NULL, dbid, NULL, InvalidOid, false, false,
1703+
dbname);
17031704
SetProcessingMode(NormalProcessing);
17041705
set_ps_display(dbname);
17051706
ereport(DEBUG1,

src/backend/postmaster/postmaster.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5668,7 +5668,11 @@ BackgroundWorkerInitializeConnection(const char *dbname, const char *username, u
56685668
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
56695669
errmsg("database connection requirement not indicated during registration")));
56705670

5671-
InitPostgres(dbname, InvalidOid, username, InvalidOid, NULL, (flags & BGWORKER_BYPASS_ALLOWCONN) != 0);
5671+
InitPostgres(dbname, InvalidOid, /* database to connect to */
5672+
username, InvalidOid, /* role to connect as */
5673+
false, /* never honor session_preload_libraries */
5674+
(flags & BGWORKER_BYPASS_ALLOWCONN) != 0, /* ignore datallowconn? */
5675+
NULL); /* no out_dbname */
56725676

56735677
/* it had better not gotten out of "init" mode yet */
56745678
if (!IsInitProcessingMode())
@@ -5691,7 +5695,11 @@ BackgroundWorkerInitializeConnectionByOid(Oid dboid, Oid useroid, uint32 flags)
56915695
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
56925696
errmsg("database connection requirement not indicated during registration")));
56935697

5694-
InitPostgres(NULL, dboid, NULL, useroid, NULL, (flags & BGWORKER_BYPASS_ALLOWCONN) != 0);
5698+
InitPostgres(NULL, dboid, /* database to connect to */
5699+
NULL, useroid, /* role to connect as */
5700+
false, /* never honor session_preload_libraries */
5701+
(flags & BGWORKER_BYPASS_ALLOWCONN) != 0, /* ignore datallowconn? */
5702+
NULL); /* no out_dbname */
56955703

56965704
/* it had better not gotten out of "init" mode yet */
56975705
if (!IsInitProcessingMode())

src/backend/tcop/postgres.c

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4152,7 +4152,11 @@ PostgresMain(const char *dbname, const char *username)
41524152
* it inside InitPostgres() instead. In particular, anything that
41534153
* involves database access should be there, not here.
41544154
*/
4155-
InitPostgres(dbname, InvalidOid, username, InvalidOid, NULL, false);
4155+
InitPostgres(dbname, InvalidOid, /* database to connect to */
4156+
username, InvalidOid, /* role to connect as */
4157+
!am_walsender, /* honor session_preload_libraries? */
4158+
false, /* don't ignore datallowconn */
4159+
NULL); /* no out_dbname */
41564160

41574161
/*
41584162
* If the PostmasterContext is still around, recycle the space; we don't
@@ -4188,12 +4192,6 @@ PostgresMain(const char *dbname, const char *username)
41884192
if (am_walsender)
41894193
InitWalSender();
41904194

4191-
/*
4192-
* process any libraries that should be preloaded at backend start (this
4193-
* likewise can't be done until GUC settings are complete)
4194-
*/
4195-
process_session_preload_libraries();
4196-
41974195
/*
41984196
* Send this backend's cancellation info to the frontend.
41994197
*/

src/backend/utils/init/postinit.c

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -622,29 +622,48 @@ BaseInit(void)
622622
* InitPostgres
623623
* Initialize POSTGRES.
624624
*
625+
* Parameters:
626+
* in_dbname, dboid: specify database to connect to, as described below
627+
* username, useroid: specify role to connect as, as described below
628+
* load_session_libraries: TRUE to honor [session|local]_preload_libraries
629+
* override_allow_connections: TRUE to connect despite !datallowconn
630+
* out_dbname: optional output parameter, see below; pass NULL if not used
631+
*
625632
* The database can be specified by name, using the in_dbname parameter, or by
626-
* OID, using the dboid parameter. In the latter case, the actual database
633+
* OID, using the dboid parameter. Specify NULL or InvalidOid respectively
634+
* for the unused parameter. If dboid is provided, the actual database
627635
* name can be returned to the caller in out_dbname. If out_dbname isn't
628636
* NULL, it must point to a buffer of size NAMEDATALEN.
629637
*
630-
* Similarly, the username can be passed by name, using the username parameter,
638+
* Similarly, the role can be passed by name, using the username parameter,
631639
* or by OID using the useroid parameter.
632640
*
633-
* In bootstrap mode no parameters are used. The autovacuum launcher process
634-
* doesn't use any parameters either, because it only goes far enough to be
635-
* able to read pg_database; it doesn't connect to any particular database.
636-
* In walsender mode only username is used.
641+
* In bootstrap mode the database and username parameters are NULL/InvalidOid.
642+
* The autovacuum launcher process doesn't specify these parameters either,
643+
* because it only goes far enough to be able to read pg_database; it doesn't
644+
* connect to any particular database. An autovacuum worker specifies a
645+
* database but not a username; conversely, a physical walsender specifies
646+
* username but not database.
647+
*
648+
* By convention, load_session_libraries should be passed as true in
649+
* "interactive" sessions (including standalone backends), but false in
650+
* background processes such as autovacuum. Note in particular that it
651+
* shouldn't be true in parallel worker processes; those have another
652+
* mechanism for replicating their leader's set of loaded libraries.
637653
*
638-
* As of PostgreSQL 8.2, we expect InitProcess() was already called, so we
639-
* already have a PGPROC struct ... but it's not completely filled in yet.
654+
* We expect that InitProcess() was already called, so we already have a
655+
* PGPROC struct ... but it's not completely filled in yet.
640656
*
641657
* Note:
642658
* Be very careful with the order of calls in the InitPostgres function.
643659
* --------------------------------
644660
*/
645661
void
646-
InitPostgres(const char *in_dbname, Oid dboid, const char *username,
647-
Oid useroid, char *out_dbname, bool override_allow_connections)
662+
InitPostgres(const char *in_dbname, Oid dboid,
663+
const char *username, Oid useroid,
664+
bool load_session_libraries,
665+
bool override_allow_connections,
666+
char *out_dbname)
648667
{
649668
bool bootstrap = IsBootstrapProcessingMode();
650669
bool am_superuser;
@@ -1108,6 +1127,16 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
11081127
/* Initialize this backend's session state. */
11091128
InitializeSession();
11101129

1130+
/*
1131+
* If this is an interactive session, load any libraries that should be
1132+
* preloaded at backend start. Since those are determined by GUCs, this
1133+
* can't happen until GUC settings are complete, but we want it to happen
1134+
* during the initial transaction in case anything that requires database
1135+
* access needs to be done.
1136+
*/
1137+
if (load_session_libraries)
1138+
process_session_preload_libraries();
1139+
11111140
/* report this backend in the PgBackendStatus array */
11121141
if (!bootstrap)
11131142
pgstat_bestart();

src/include/miscadmin.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -457,8 +457,11 @@ extern PGDLLIMPORT AuxProcType MyAuxProcType;
457457
/* in utils/init/postinit.c */
458458
extern void pg_split_opts(char **argv, int *argcp, const char *optstr);
459459
extern void InitializeMaxBackends(void);
460-
extern void InitPostgres(const char *in_dbname, Oid dboid, const char *username,
461-
Oid useroid, char *out_dbname, bool override_allow_connections);
460+
extern void InitPostgres(const char *in_dbname, Oid dboid,
461+
const char *username, Oid useroid,
462+
bool load_session_libraries,
463+
bool override_allow_connections,
464+
char *out_dbname);
462465
extern void BaseInit(void);
463466

464467
/* in utils/init/miscinit.c */

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy