PostgreSQL Source Code git master
postinit.c File Reference
#include "postgres.h"
#include <ctype.h>
#include <fcntl.h>
#include <unistd.h>
#include "access/genam.h"
#include "access/heapam.h"
#include "access/htup_details.h"
#include "access/session.h"
#include "access/tableam.h"
#include "access/xact.h"
#include "access/xlog.h"
#include "access/xloginsert.h"
#include "catalog/namespace.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_database.h"
#include "catalog/pg_db_role_setting.h"
#include "catalog/pg_tablespace.h"
#include "libpq/auth.h"
#include "libpq/libpq-be.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "pgstat.h"
#include "postmaster/autovacuum.h"
#include "postmaster/postmaster.h"
#include "replication/slot.h"
#include "replication/slotsync.h"
#include "replication/walsender.h"
#include "storage/aio_subsys.h"
#include "storage/bufmgr.h"
#include "storage/fd.h"
#include "storage/ipc.h"
#include "storage/lmgr.h"
#include "storage/proc.h"
#include "storage/procarray.h"
#include "storage/procnumber.h"
#include "storage/procsignal.h"
#include "storage/sinvaladt.h"
#include "storage/smgr.h"
#include "storage/sync.h"
#include "tcop/backend_startup.h"
#include "tcop/tcopprot.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/guc_hooks.h"
#include "utils/injection_point.h"
#include "utils/memutils.h"
#include "utils/pg_locale.h"
#include "utils/portal.h"
#include "utils/ps_status.h"
#include "utils/snapmgr.h"
#include "utils/syscache.h"
#include "utils/timeout.h"
Include dependency graph for postinit.c:

Go to the source code of this file.

Functions

static HeapTuple GetDatabaseTuple (const char *dbname)
 
static HeapTuple GetDatabaseTupleByOid (Oid dboid)
 
static void PerformAuthentication (Port *port)
 
static void CheckMyDatabase (const char *name, bool am_superuser, bool override_allow_connections)
 
static void ShutdownPostgres (int code, Datum arg)
 
static void StatementTimeoutHandler (void)
 
static void LockTimeoutHandler (void)
 
static void IdleInTransactionSessionTimeoutHandler (void)
 
static void TransactionTimeoutHandler (void)
 
static void IdleSessionTimeoutHandler (void)
 
static void IdleStatsUpdateTimeoutHandler (void)
 
static void ClientCheckTimeoutHandler (void)
 
static bool ThereIsAtLeastOneRole (void)
 
static void process_startup_options (Port *port, bool am_superuser)
 
static void process_settings (Oid databaseid, Oid roleid)
 
void pg_split_opts (char **argv, int *argcp, const char *optstr)
 
void InitializeMaxBackends (void)
 
void InitializeFastPathLocks (void)
 
void BaseInit (void)
 
void InitPostgres (const char *in_dbname, Oid dboid, const char *username, Oid useroid, bits32 flags, char *out_dbname)
 

Function Documentation

◆ BaseInit()

void BaseInit ( void  )

Definition at line 612 of file postinit.c.

613{
614 Assert(MyProc != NULL);
615
616 /*
617 * Initialize our input/output/debugging file descriptors.
618 */
620
621 /*
622 * Initialize file access. Done early so other subsystems can access
623 * files.
624 */
626
627 /*
628 * Initialize statistics reporting. This needs to happen early to ensure
629 * that pgstat's shutdown callback runs after the shutdown callbacks of
630 * all subsystems that can produce stats (like e.g. transaction commits
631 * can).
632 */
634
635 /*
636 * Initialize AIO before infrastructure that might need to actually
637 * execute AIO.
638 */
640
641 /* Do local initialization of storage and buffer managers */
642 InitSync();
643 smgrinit();
645
646 /*
647 * Initialize temporary file access after pgstat, so that the temporary
648 * file shutdown hook can report temporary file statistics.
649 */
651
652 /*
653 * Initialize local buffers for WAL record construction, in case we ever
654 * try to insert XLOG.
655 */
657
658 /* Initialize lock manager's local structs */
660
661 /*
662 * Initialize replication slots after pgstat. The exit hook might need to
663 * drop ephemeral slots, which in turn triggers stats reporting.
664 */
666
667 /*
668 * The before shmem exit callback frees the DSA memory occupied by the
669 * latest memory context statistics that could be published by this proc
670 * if requested.
671 */
673}
void pgaio_init_backend(void)
Definition: aio_init.c:222
void InitBufferManagerAccess(void)
Definition: bufmgr.c:4013
void DebugFileOpen(void)
Definition: elog.c:2116
void InitFileAccess(void)
Definition: fd.c:903
void InitTemporaryFileAccess(void)
Definition: fd.c:933
Assert(PointerIsAligned(start, uint64))
void before_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:337
void InitLockManagerAccess(void)
Definition: lock.c:504
void AtProcExit_memstats_cleanup(int code, Datum arg)
Definition: mcxt.c:1913
void pgstat_initialize(void)
Definition: pgstat.c:638
void ReplicationSlotInitialize(void)
Definition: slot.c:239
void smgrinit(void)
Definition: smgr.c:188
PGPROC * MyProc
Definition: proc.c:67
void InitSync(void)
Definition: sync.c:124
void InitXLogInsert(void)
Definition: xloginsert.c:1348

References Assert(), AtProcExit_memstats_cleanup(), before_shmem_exit(), DebugFileOpen(), InitBufferManagerAccess(), InitFileAccess(), InitLockManagerAccess(), InitSync(), InitTemporaryFileAccess(), InitXLogInsert(), MyProc, pgaio_init_backend(), pgstat_initialize(), ReplicationSlotInitialize(), and smgrinit().

Referenced by AutoVacLauncherMain(), AutoVacWorkerMain(), AuxiliaryProcessMainCommon(), BackgroundWorkerMain(), BootstrapModeMain(), PostgresMain(), and ReplSlotSyncWorkerMain().

◆ CheckMyDatabase()

static void CheckMyDatabase ( const char *  name,
bool  am_superuser,
bool  override_allow_connections 
)
static

Definition at line 323 of file postinit.c.

324{
325 HeapTuple tup;
326 Form_pg_database dbform;
327 Datum datum;
328 bool isnull;
329 char *collate;
330 char *ctype;
331
332 /* Fetch our pg_database row normally, via syscache */
333 tup = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(MyDatabaseId));
334 if (!HeapTupleIsValid(tup))
335 elog(ERROR, "cache lookup failed for database %u", MyDatabaseId);
336 dbform = (Form_pg_database) GETSTRUCT(tup);
337
338 /* This recheck is strictly paranoia */
339 if (strcmp(name, NameStr(dbform->datname)) != 0)
341 (errcode(ERRCODE_UNDEFINED_DATABASE),
342 errmsg("database \"%s\" has disappeared from pg_database",
343 name),
344 errdetail("Database OID %u now seems to belong to \"%s\".",
345 MyDatabaseId, NameStr(dbform->datname))));
346
347 /*
348 * Check permissions to connect to the database.
349 *
350 * These checks are not enforced when in standalone mode, so that there is
351 * a way to recover from disabling all access to all databases, for
352 * example "UPDATE pg_database SET datallowconn = false;".
353 */
355 {
356 /*
357 * Check that the database is currently allowing connections.
358 * (Background processes can override this test and the next one by
359 * setting override_allow_connections.)
360 */
361 if (!dbform->datallowconn && !override_allow_connections)
363 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
364 errmsg("database \"%s\" is not currently accepting connections",
365 name)));
366
367 /*
368 * Check privilege to connect to the database. (The am_superuser test
369 * is redundant, but since we have the flag, might as well check it
370 * and save a few cycles.)
371 */
372 if (!am_superuser && !override_allow_connections &&
373 object_aclcheck(DatabaseRelationId, MyDatabaseId, GetUserId(),
376 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
377 errmsg("permission denied for database \"%s\"", name),
378 errdetail("User does not have CONNECT privilege.")));
379
380 /*
381 * Check connection limit for this database. We enforce the limit
382 * only for regular backends, since other process types have their own
383 * PGPROC pools.
384 *
385 * There is a race condition here --- we create our PGPROC before
386 * checking for other PGPROCs. If two backends did this at about the
387 * same time, they might both think they were over the limit, while
388 * ideally one should succeed and one fail. Getting that to work
389 * exactly seems more trouble than it is worth, however; instead we
390 * just document that the connection limit is approximate.
391 */
392 if (dbform->datconnlimit >= 0 &&
394 !am_superuser &&
395 CountDBConnections(MyDatabaseId) > dbform->datconnlimit)
397 (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
398 errmsg("too many connections for database \"%s\"",
399 name)));
400 }
401
402 /*
403 * OK, we're golden. Next to-do item is to save the encoding info out of
404 * the pg_database tuple.
405 */
406 SetDatabaseEncoding(dbform->encoding);
407 /* Record it as a GUC internal option, too */
408 SetConfigOption("server_encoding", GetDatabaseEncodingName(),
410 /* If we have no other source of client_encoding, use server encoding */
411 SetConfigOption("client_encoding", GetDatabaseEncodingName(),
413
414 /* assign locale variables */
415 datum = SysCacheGetAttrNotNull(DATABASEOID, tup, Anum_pg_database_datcollate);
416 collate = TextDatumGetCString(datum);
417 datum = SysCacheGetAttrNotNull(DATABASEOID, tup, Anum_pg_database_datctype);
418 ctype = TextDatumGetCString(datum);
419
420 if (pg_perm_setlocale(LC_COLLATE, collate) == NULL)
422 (errmsg("database locale is incompatible with operating system"),
423 errdetail("The database was initialized with LC_COLLATE \"%s\", "
424 " which is not recognized by setlocale().", collate),
425 errhint("Recreate the database with another locale or install the missing locale.")));
426
427 if (pg_perm_setlocale(LC_CTYPE, ctype) == NULL)
429 (errmsg("database locale is incompatible with operating system"),
430 errdetail("The database was initialized with LC_CTYPE \"%s\", "
431 " which is not recognized by setlocale().", ctype),
432 errhint("Recreate the database with another locale or install the missing locale.")));
433
434 if (strcmp(ctype, "C") == 0 ||
435 strcmp(ctype, "POSIX") == 0)
436 database_ctype_is_c = true;
437
439
440 /*
441 * Check collation version. See similar code in
442 * pg_newlocale_from_collation(). Note that here we warn instead of error
443 * in any case, so that we don't prevent connecting.
444 */
445 datum = SysCacheGetAttr(DATABASEOID, tup, Anum_pg_database_datcollversion,
446 &isnull);
447 if (!isnull)
448 {
449 char *actual_versionstr;
450 char *collversionstr;
451 char *locale;
452
453 collversionstr = TextDatumGetCString(datum);
454
455 if (dbform->datlocprovider == COLLPROVIDER_LIBC)
456 locale = collate;
457 else
458 {
459 datum = SysCacheGetAttrNotNull(DATABASEOID, tup, Anum_pg_database_datlocale);
461 }
462
463 actual_versionstr = get_collation_actual_version(dbform->datlocprovider, locale);
464 if (!actual_versionstr)
465 /* should not happen */
467 "database \"%s\" has no actual collation version, but a version was recorded",
468 name);
469 else if (strcmp(actual_versionstr, collversionstr) != 0)
471 (errmsg("database \"%s\" has a collation version mismatch",
472 name),
473 errdetail("The database was created using collation version %s, "
474 "but the operating system provides version %s.",
475 collversionstr, actual_versionstr),
476 errhint("Rebuild all objects in this database that use the default collation and run "
477 "ALTER DATABASE %s REFRESH COLLATION VERSION, "
478 "or build PostgreSQL with the right library version.",
480 }
481
482 ReleaseSysCache(tup);
483}
@ ACLCHECK_OK
Definition: acl.h:183
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition: aclchk.c:3821
#define TextDatumGetCString(d)
Definition: builtins.h:98
#define NameStr(name)
Definition: c.h:717
int errdetail(const char *fmt,...)
Definition: elog.c:1204
int errhint(const char *fmt,...)
Definition: elog.c:1318
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#define FATAL
Definition: elog.h:41
#define WARNING
Definition: elog.h:36
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#define ereport(elevel,...)
Definition: elog.h:149
bool IsUnderPostmaster
Definition: globals.c:121
Oid MyDatabaseId
Definition: globals.c:95
void SetConfigOption(const char *name, const char *value, GucContext context, GucSource source)
Definition: guc.c:4332
@ PGC_S_DYNAMIC_DEFAULT
Definition: guc.h:114
@ PGC_INTERNAL
Definition: guc.h:73
@ PGC_BACKEND
Definition: guc.h:77
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
Definition: htup_details.h:728
static char * locale
Definition: initdb.c:140
const char * GetDatabaseEncodingName(void)
Definition: mbutils.c:1267
void SetDatabaseEncoding(int encoding)
Definition: mbutils.c:1161
#define AmRegularBackendProcess()
Definition: miscadmin.h:381
Oid GetUserId(void)
Definition: miscinit.c:520
#define ACL_CONNECT
Definition: parsenodes.h:87
FormData_pg_database * Form_pg_database
Definition: pg_database.h:96
char * get_collation_actual_version(char collprovider, const char *collcollate)
Definition: pg_locale.c:1239
bool database_ctype_is_c
Definition: pg_locale.c:128
char * pg_perm_setlocale(int category, const char *locale)
Definition: pg_locale.c:190
void init_database_collation(void)
Definition: pg_locale.c:1146
uintptr_t Datum
Definition: postgres.h:69
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:257
int CountDBConnections(Oid databaseid)
Definition: procarray.c:3628
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:13019
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:269
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:221
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:600
Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition: syscache.c:631
const char * name

References ACL_CONNECT, ACLCHECK_OK, AmRegularBackendProcess, CountDBConnections(), database_ctype_is_c, elog, ereport, errcode(), errdetail(), errhint(), errmsg(), ERROR, FATAL, get_collation_actual_version(), GetDatabaseEncodingName(), GETSTRUCT(), GetUserId(), HeapTupleIsValid, init_database_collation(), IsUnderPostmaster, locale, MyDatabaseId, name, NameStr, object_aclcheck(), ObjectIdGetDatum(), pg_perm_setlocale(), PGC_BACKEND, PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT, quote_identifier(), ReleaseSysCache(), SearchSysCache1(), SetConfigOption(), SetDatabaseEncoding(), SysCacheGetAttr(), SysCacheGetAttrNotNull(), TextDatumGetCString, and WARNING.

Referenced by InitPostgres().

◆ ClientCheckTimeoutHandler()

static void ClientCheckTimeoutHandler ( void  )
static

Definition at line 1431 of file postinit.c.

1432{
1434 InterruptPending = true;
1436}
volatile sig_atomic_t InterruptPending
Definition: globals.c:32
struct Latch * MyLatch
Definition: globals.c:64
volatile sig_atomic_t CheckClientConnectionPending
Definition: globals.c:35
void SetLatch(Latch *latch)
Definition: latch.c:288

References CheckClientConnectionPending, InterruptPending, MyLatch, and SetLatch().

Referenced by InitPostgres().

◆ GetDatabaseTuple()

static HeapTuple GetDatabaseTuple ( const char *  dbname)
static

Definition at line 105 of file postinit.c.

106{
107 HeapTuple tuple;
108 Relation relation;
109 SysScanDesc scan;
110 ScanKeyData key[1];
111
112 /*
113 * form a scan key
114 */
115 ScanKeyInit(&key[0],
116 Anum_pg_database_datname,
117 BTEqualStrategyNumber, F_NAMEEQ,
119
120 /*
121 * Open pg_database and fetch a tuple. Force heap scan if we haven't yet
122 * built the critical shared relcache entries (i.e., we're starting up
123 * without a shared relcache cache file).
124 */
125 relation = table_open(DatabaseRelationId, AccessShareLock);
126 scan = systable_beginscan(relation, DatabaseNameIndexId,
128 NULL,
129 1, key);
130
131 tuple = systable_getnext(scan);
132
133 /* Must copy tuple before releasing buffer */
134 if (HeapTupleIsValid(tuple))
135 tuple = heap_copytuple(tuple);
136
137 /* all done */
138 systable_endscan(scan);
139 table_close(relation, AccessShareLock);
140
141 return tuple;
142}
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:603
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:514
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:388
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:778
#define AccessShareLock
Definition: lockdefs.h:36
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:355
bool criticalSharedRelcachesBuilt
Definition: relcache.c:146
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define BTEqualStrategyNumber
Definition: stratnum.h:31
char * dbname
Definition: streamutil.c:49
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40

References AccessShareLock, BTEqualStrategyNumber, criticalSharedRelcachesBuilt, CStringGetDatum(), dbname, heap_copytuple(), HeapTupleIsValid, sort-test::key, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by InitPostgres().

◆ GetDatabaseTupleByOid()

static HeapTuple GetDatabaseTupleByOid ( Oid  dboid)
static

Definition at line 148 of file postinit.c.

149{
150 HeapTuple tuple;
151 Relation relation;
152 SysScanDesc scan;
153 ScanKeyData key[1];
154
155 /*
156 * form a scan key
157 */
158 ScanKeyInit(&key[0],
159 Anum_pg_database_oid,
160 BTEqualStrategyNumber, F_OIDEQ,
161 ObjectIdGetDatum(dboid));
162
163 /*
164 * Open pg_database and fetch a tuple. Force heap scan if we haven't yet
165 * built the critical shared relcache entries (i.e., we're starting up
166 * without a shared relcache cache file).
167 */
168 relation = table_open(DatabaseRelationId, AccessShareLock);
169 scan = systable_beginscan(relation, DatabaseOidIndexId,
171 NULL,
172 1, key);
173
174 tuple = systable_getnext(scan);
175
176 /* Must copy tuple before releasing buffer */
177 if (HeapTupleIsValid(tuple))
178 tuple = heap_copytuple(tuple);
179
180 /* all done */
181 systable_endscan(scan);
182 table_close(relation, AccessShareLock);
183
184 return tuple;
185}

References AccessShareLock, BTEqualStrategyNumber, criticalSharedRelcachesBuilt, heap_copytuple(), HeapTupleIsValid, sort-test::key, ObjectIdGetDatum(), ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by InitPostgres().

◆ IdleInTransactionSessionTimeoutHandler()

static void IdleInTransactionSessionTimeoutHandler ( void  )
static

Definition at line 1407 of file postinit.c.

1408{
1410 InterruptPending = true;
1412}
volatile sig_atomic_t IdleInTransactionSessionTimeoutPending
Definition: globals.c:37

References IdleInTransactionSessionTimeoutPending, InterruptPending, MyLatch, and SetLatch().

Referenced by InitPostgres().

◆ IdleSessionTimeoutHandler()

static void IdleSessionTimeoutHandler ( void  )
static

Definition at line 1415 of file postinit.c.

1416{
1418 InterruptPending = true;
1420}
volatile sig_atomic_t IdleSessionTimeoutPending
Definition: globals.c:39

References IdleSessionTimeoutPending, InterruptPending, MyLatch, and SetLatch().

Referenced by InitPostgres().

◆ IdleStatsUpdateTimeoutHandler()

static void IdleStatsUpdateTimeoutHandler ( void  )
static

Definition at line 1423 of file postinit.c.

1424{
1426 InterruptPending = true;
1428}
volatile sig_atomic_t IdleStatsUpdateTimeoutPending
Definition: globals.c:43

References IdleStatsUpdateTimeoutPending, InterruptPending, MyLatch, and SetLatch().

Referenced by InitPostgres().

◆ InitializeFastPathLocks()

void InitializeFastPathLocks ( void  )

Definition at line 580 of file postinit.c.

581{
582 /* Should be initialized only once. */
584
585 /*
586 * Based on the max_locks_per_transaction GUC, as that's a good indicator
587 * of the expected number of locks, figure out the value for
588 * FastPathLockGroupsPerBackend. This must be a power-of-two. We cap the
589 * value at FP_LOCK_GROUPS_PER_BACKEND_MAX and insist the value is at
590 * least 1.
591 *
592 * The default max_locks_per_transaction = 64 means 4 groups by default.
593 */
597
598 /* Validate we did get a power-of-two */
601}
#define Min(x, y)
Definition: c.h:975
#define Max(x, y)
Definition: c.h:969
int max_locks_per_xact
Definition: lock.c:53
int FastPathLockGroupsPerBackend
Definition: lock.c:202
static uint32 pg_nextpower2_32(uint32 num)
Definition: pg_bitutils.h:189
#define FP_LOCK_GROUPS_PER_BACKEND_MAX
Definition: proc.h:91
#define FP_LOCK_SLOTS_PER_GROUP
Definition: proc.h:92

References Assert(), FastPathLockGroupsPerBackend, FP_LOCK_GROUPS_PER_BACKEND_MAX, FP_LOCK_SLOTS_PER_GROUP, Max, max_locks_per_xact, Min, and pg_nextpower2_32().

Referenced by BootstrapModeMain(), PostgresSingleUserMain(), and PostmasterMain().

◆ InitializeMaxBackends()

void InitializeMaxBackends ( void  )

Definition at line 555 of file postinit.c.

556{
557 Assert(MaxBackends == 0);
558
559 /* Note that this does not include "auxiliary" processes */
562
565 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
566 errmsg("too many server processes configured"),
567 errdetail("\"max_connections\" (%d) plus \"autovacuum_worker_slots\" (%d) plus \"max_worker_processes\" (%d) plus \"max_wal_senders\" (%d) must be less than %d.",
571}
int autovacuum_worker_slots
Definition: autovacuum.c:119
int MaxConnections
Definition: globals.c:144
int MaxBackends
Definition: globals.c:147
int max_worker_processes
Definition: globals.c:145
#define NUM_SPECIAL_WORKER_PROCS
Definition: proc.h:442
#define MAX_BACKENDS
Definition: procnumber.h:39
int max_wal_senders
Definition: walsender.c:126

References Assert(), autovacuum_worker_slots, ereport, errcode(), errdetail(), errmsg(), ERROR, MAX_BACKENDS, max_wal_senders, max_worker_processes, MaxBackends, MaxConnections, and NUM_SPECIAL_WORKER_PROCS.

Referenced by BootstrapModeMain(), PostgresSingleUserMain(), and PostmasterMain().

◆ InitPostgres()

void InitPostgres ( const char *  in_dbname,
Oid  dboid,
const char *  username,
Oid  useroid,
bits32  flags,
char *  out_dbname 
)

Definition at line 719 of file postinit.c.

723{
724 bool bootstrap = IsBootstrapProcessingMode();
725 bool am_superuser;
726 char *fullpath;
727 char dbname[NAMEDATALEN];
728 int nfree = 0;
729
730 elog(DEBUG3, "InitPostgres");
731
732 /*
733 * Add my PGPROC struct to the ProcArray.
734 *
735 * Once I have done this, I am visible to other backends!
736 */
738
739 /* Initialize status reporting */
741
742 /*
743 * And initialize an entry in the PgBackendStatus array. That way, if
744 * LWLocks or third-party authentication should happen to hang, it is
745 * possible to retrieve some information about what is going on.
746 */
747 if (!bootstrap)
748 {
750 INJECTION_POINT("init-pre-auth");
751 }
752
753 /*
754 * Initialize my entry in the shared-invalidation manager's array of
755 * per-backend data.
756 */
758
760
761 /*
762 * Also set up timeout handlers needed for backend operation. We need
763 * these in every case except bootstrap.
764 */
765 if (!bootstrap)
766 {
777 }
778
779 /*
780 * If this is either a bootstrap process or a standalone backend, start up
781 * the XLOG machinery, and register to have it closed down at exit. In
782 * other cases, the startup process is responsible for starting up the
783 * XLOG machinery, and the checkpointer for closing it down.
784 */
786 {
787 /*
788 * We don't yet have an aux-process resource owner, but StartupXLOG
789 * and ShutdownXLOG will need one. Hence, create said resource owner
790 * (and register a callback to clean it up after ShutdownXLOG runs).
791 */
793
794 StartupXLOG();
795 /* Release (and warn about) any buffer pins leaked in StartupXLOG */
797 /* Reset CurrentResourceOwner to nothing for the moment */
799
800 /*
801 * Use before_shmem_exit() so that ShutdownXLOG() can rely on DSM
802 * segments etc to work (which in turn is required for pgstats).
803 */
806 }
807
808 /*
809 * Initialize the relation cache and the system catalog caches. Note that
810 * no catalog access happens here; we only set up the hashtable structure.
811 * We must do this before starting a transaction because transaction abort
812 * would try to touch these hashtables.
813 */
817
818 /* Initialize portal manager */
820
821 /*
822 * Load relcache entries for the shared system catalogs. This must create
823 * at least entries for pg_database and catalogs used for authentication.
824 */
826
827 /*
828 * Set up process-exit callback to do pre-shutdown cleanup. This is the
829 * one of the first before_shmem_exit callbacks we register; thus, this
830 * will be one the last things we do before low-level modules like the
831 * buffer manager begin to close down. We need to have this in place
832 * before we begin our first transaction --- if we fail during the
833 * initialization transaction, as is entirely possible, we need the
834 * AbortTransaction call to clean up.
835 */
837
838 /* The autovacuum launcher is done here */
840 {
841 /* fill in the remainder of this entry in the PgBackendStatus array */
843
844 return;
845 }
846
847 /*
848 * Start a new transaction here before first access to db.
849 */
850 if (!bootstrap)
851 {
852 /* statement_timestamp must be set for timeouts to work correctly */
855
856 /*
857 * transaction_isolation will have been set to the default by the
858 * above. If the default is "serializable", and we are in hot
859 * standby, we will fail if we don't change it to something lower.
860 * Fortunately, "read committed" is plenty good enough.
861 */
863 }
864
865 /*
866 * Perform client authentication if necessary, then figure out our
867 * postgres user ID, and see if we are a superuser.
868 *
869 * In standalone mode, autovacuum worker processes and slot sync worker
870 * process, we use a fixed ID, otherwise we figure it out from the
871 * authenticated user name.
872 */
874 {
876 am_superuser = true;
877 }
878 else if (!IsUnderPostmaster)
879 {
881 am_superuser = true;
884 (errcode(ERRCODE_UNDEFINED_OBJECT),
885 errmsg("no roles are defined in this database system"),
886 errhint("You should immediately run CREATE USER \"%s\" SUPERUSER;.",
887 username != NULL ? username : "postgres")));
888 }
889 else if (AmBackgroundWorkerProcess())
890 {
891 if (username == NULL && !OidIsValid(useroid))
892 {
894 am_superuser = true;
895 }
896 else
897 {
899 (flags & INIT_PG_OVERRIDE_ROLE_LOGIN) != 0);
900 am_superuser = superuser();
901 }
902 }
903 else
904 {
905 /* normal multiuser case */
906 Assert(MyProcPort != NULL);
908 InitializeSessionUserId(username, useroid, false);
909 /* ensure that auth_method is actually valid, aka authn_id is not NULL */
913 am_superuser = superuser();
914 }
915
916 /* Report any SSL/GSS details for the session. */
917 if (MyProcPort != NULL)
918 {
919 Assert(!bootstrap);
920
922 }
923
924 /*
925 * Binary upgrades only allowed super-user connections
926 */
927 if (IsBinaryUpgrade && !am_superuser)
928 {
930 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
931 errmsg("must be superuser to connect in binary upgrade mode")));
932 }
933
934 /*
935 * The last few regular connection slots are reserved for superusers and
936 * roles with privileges of pg_use_reserved_connections. We do not apply
937 * these limits to background processes, since they all have their own
938 * pools of PGPROC slots.
939 *
940 * Note: At this point, the new backend has already claimed a proc struct,
941 * so we must check whether the number of free slots is strictly less than
942 * the reserved connection limits.
943 */
944 if (AmRegularBackendProcess() && !am_superuser &&
947 {
950 (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
951 errmsg("remaining connection slots are reserved for roles with the %s attribute",
952 "SUPERUSER")));
953
954 if (!has_privs_of_role(GetUserId(), ROLE_PG_USE_RESERVED_CONNECTIONS))
956 (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
957 errmsg("remaining connection slots are reserved for roles with privileges of the \"%s\" role",
958 "pg_use_reserved_connections")));
959 }
960
961 /* Check replication permissions needed for walsender processes. */
962 if (am_walsender)
963 {
964 Assert(!bootstrap);
965
968 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
969 errmsg("permission denied to start WAL sender"),
970 errdetail("Only roles with the %s attribute may start a WAL sender process.",
971 "REPLICATION")));
972 }
973
974 /*
975 * If this is a plain walsender only supporting physical replication, we
976 * don't want to connect to any particular database. Just finish the
977 * backend startup by processing any options from the startup packet, and
978 * we're done.
979 */
981 {
982 /* process any options passed in the startup packet */
983 if (MyProcPort != NULL)
984 process_startup_options(MyProcPort, am_superuser);
985
986 /* Apply PostAuthDelay as soon as we've read all options */
987 if (PostAuthDelay > 0)
988 pg_usleep(PostAuthDelay * 1000000L);
989
990 /* initialize client encoding */
992
993 /* fill in the remainder of this entry in the PgBackendStatus array */
995
996 /* close the transaction we started above */
998
999 return;
1000 }
1001
1002 /*
1003 * Set up the global variables holding database id and default tablespace.
1004 * But note we won't actually try to touch the database just yet.
1005 *
1006 * We take a shortcut in the bootstrap case, otherwise we have to look up
1007 * the db's entry in pg_database.
1008 */
1009 if (bootstrap)
1010 {
1011 dboid = Template1DbOid;
1012 MyDatabaseTableSpace = DEFAULTTABLESPACE_OID;
1013 }
1014 else if (in_dbname != NULL)
1015 {
1016 HeapTuple tuple;
1017 Form_pg_database dbform;
1018
1019 tuple = GetDatabaseTuple(in_dbname);
1020 if (!HeapTupleIsValid(tuple))
1021 ereport(FATAL,
1022 (errcode(ERRCODE_UNDEFINED_DATABASE),
1023 errmsg("database \"%s\" does not exist", in_dbname)));
1024 dbform = (Form_pg_database) GETSTRUCT(tuple);
1025 dboid = dbform->oid;
1026 }
1027 else if (!OidIsValid(dboid))
1028 {
1029 /*
1030 * If this is a background worker not bound to any particular
1031 * database, we're done now. Everything that follows only makes sense
1032 * if we are bound to a specific database. We do need to close the
1033 * transaction we started before returning.
1034 */
1035 if (!bootstrap)
1036 {
1039 }
1040 return;
1041 }
1042
1043 /*
1044 * Now, take a writer's lock on the database we are trying to connect to.
1045 * If there is a concurrently running DROP DATABASE on that database, this
1046 * will block us until it finishes (and has committed its update of
1047 * pg_database).
1048 *
1049 * Note that the lock is not held long, only until the end of this startup
1050 * transaction. This is OK since we will advertise our use of the
1051 * database in the ProcArray before dropping the lock (in fact, that's the
1052 * next thing to do). Anyone trying a DROP DATABASE after this point will
1053 * see us in the array once they have the lock. Ordering is important for
1054 * this because we don't want to advertise ourselves as being in this
1055 * database until we have the lock; otherwise we create what amounts to a
1056 * deadlock with CountOtherDBBackends().
1057 *
1058 * Note: use of RowExclusiveLock here is reasonable because we envision
1059 * our session as being a concurrent writer of the database. If we had a
1060 * way of declaring a session as being guaranteed-read-only, we could use
1061 * AccessShareLock for such sessions and thereby not conflict against
1062 * CREATE DATABASE.
1063 */
1064 if (!bootstrap)
1065 LockSharedObject(DatabaseRelationId, dboid, 0, RowExclusiveLock);
1066
1067 /*
1068 * Recheck pg_database to make sure the target database hasn't gone away.
1069 * If there was a concurrent DROP DATABASE, this ensures we will die
1070 * cleanly without creating a mess.
1071 */
1072 if (!bootstrap)
1073 {
1074 HeapTuple tuple;
1075 Form_pg_database datform;
1076
1077 tuple = GetDatabaseTupleByOid(dboid);
1078 if (HeapTupleIsValid(tuple))
1079 datform = (Form_pg_database) GETSTRUCT(tuple);
1080
1081 if (!HeapTupleIsValid(tuple) ||
1082 (in_dbname && namestrcmp(&datform->datname, in_dbname)))
1083 {
1084 if (in_dbname)
1085 ereport(FATAL,
1086 (errcode(ERRCODE_UNDEFINED_DATABASE),
1087 errmsg("database \"%s\" does not exist", in_dbname),
1088 errdetail("It seems to have just been dropped or renamed.")));
1089 else
1090 ereport(FATAL,
1091 (errcode(ERRCODE_UNDEFINED_DATABASE),
1092 errmsg("database %u does not exist", dboid)));
1093 }
1094
1095 strlcpy(dbname, NameStr(datform->datname), sizeof(dbname));
1096
1097 if (database_is_invalid_form(datform))
1098 {
1099 ereport(FATAL,
1100 errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1101 errmsg("cannot connect to invalid database \"%s\"", dbname),
1102 errhint("Use DROP DATABASE to drop invalid databases."));
1103 }
1104
1105 MyDatabaseTableSpace = datform->dattablespace;
1106 MyDatabaseHasLoginEventTriggers = datform->dathasloginevt;
1107 /* pass the database name back to the caller */
1108 if (out_dbname)
1109 strcpy(out_dbname, dbname);
1110 }
1111
1112 /*
1113 * Now that we rechecked, we are certain to be connected to a database and
1114 * thus can set MyDatabaseId.
1115 *
1116 * It is important that MyDatabaseId only be set once we are sure that the
1117 * target database can no longer be concurrently dropped or renamed. For
1118 * example, without this guarantee, pgstat_update_dbstats() could create
1119 * entries for databases that were just dropped in the pgstat shutdown
1120 * callback, which could confuse other code paths like the autovacuum
1121 * scheduler.
1122 */
1123 MyDatabaseId = dboid;
1124
1125 /*
1126 * Now we can mark our PGPROC entry with the database ID.
1127 *
1128 * We assume this is an atomic store so no lock is needed; though actually
1129 * things would work fine even if it weren't atomic. Anyone searching the
1130 * ProcArray for this database's ID should hold the database lock, so they
1131 * would not be executing concurrently with this store. A process looking
1132 * for another database's ID could in theory see a chance match if it read
1133 * a partially-updated databaseId value; but as long as all such searches
1134 * wait and retry, as in CountOtherDBBackends(), they will certainly see
1135 * the correct value on their next try.
1136 */
1138
1139 /*
1140 * We established a catalog snapshot while reading pg_authid and/or
1141 * pg_database; but until we have set up MyDatabaseId, we won't react to
1142 * incoming sinval messages for unshared catalogs, so we won't realize it
1143 * if the snapshot has been invalidated. Assume it's no good anymore.
1144 */
1146
1147 /*
1148 * Now we should be able to access the database directory safely. Verify
1149 * it's there and looks reasonable.
1150 */
1152
1153 if (!bootstrap)
1154 {
1155 if (access(fullpath, F_OK) == -1)
1156 {
1157 if (errno == ENOENT)
1158 ereport(FATAL,
1159 (errcode(ERRCODE_UNDEFINED_DATABASE),
1160 errmsg("database \"%s\" does not exist",
1161 dbname),
1162 errdetail("The database subdirectory \"%s\" is missing.",
1163 fullpath)));
1164 else
1165 ereport(FATAL,
1167 errmsg("could not access directory \"%s\": %m",
1168 fullpath)));
1169 }
1170
1171 ValidatePgVersion(fullpath);
1172 }
1173
1174 SetDatabasePath(fullpath);
1175 pfree(fullpath);
1176
1177 /*
1178 * It's now possible to do real access to the system catalogs.
1179 *
1180 * Load relcache entries for the system catalogs. This must create at
1181 * least the minimum set of "nailed-in" cache entries.
1182 */
1184
1185 /* set up ACL framework (so CheckMyDatabase can check permissions) */
1187
1188 /*
1189 * Re-read the pg_database row for our database, check permissions and set
1190 * up database-specific GUC settings. We can't do this until all the
1191 * database-access infrastructure is up. (Also, it wants to know if the
1192 * user is a superuser, so the above stuff has to happen first.)
1193 */
1194 if (!bootstrap)
1195 CheckMyDatabase(dbname, am_superuser,
1196 (flags & INIT_PG_OVERRIDE_ALLOW_CONNS) != 0);
1197
1198 /*
1199 * Now process any command-line switches and any additional GUC variable
1200 * settings passed in the startup packet. We couldn't do this before
1201 * because we didn't know if client is a superuser.
1202 */
1203 if (MyProcPort != NULL)
1204 process_startup_options(MyProcPort, am_superuser);
1205
1206 /* Process pg_db_role_setting options */
1208
1209 /* Apply PostAuthDelay as soon as we've read all options */
1210 if (PostAuthDelay > 0)
1211 pg_usleep(PostAuthDelay * 1000000L);
1212
1213 /*
1214 * Initialize various default states that can't be set up until we've
1215 * selected the active user and gotten the right GUC settings.
1216 */
1217
1218 /* set default namespace search path */
1220
1221 /* initialize client encoding */
1223
1224 /* Initialize this backend's session state. */
1226
1227 /*
1228 * If this is an interactive session, load any libraries that should be
1229 * preloaded at backend start. Since those are determined by GUCs, this
1230 * can't happen until GUC settings are complete, but we want it to happen
1231 * during the initial transaction in case anything that requires database
1232 * access needs to be done.
1233 */
1234 if ((flags & INIT_PG_LOAD_SESSION_LIBS) != 0)
1236
1237 /* fill in the remainder of this entry in the PgBackendStatus array */
1238 if (!bootstrap)
1240
1241 /* close the transaction we started above */
1242 if (!bootstrap)
1244}
void initialize_acl(void)
Definition: acl.c:5024
bool has_privs_of_role(Oid member, Oid role)
Definition: acl.c:5268
void pgstat_bestart_security(void)
void pgstat_bestart_initial(void)
void pgstat_beinit(void)
void pgstat_bestart_final(void)
#define OidIsValid(objectId)
Definition: c.h:746
bool database_is_invalid_form(Form_pg_database datform)
Definition: dbcommands.c:3212
int errcode_for_file_access(void)
Definition: elog.c:877
#define DEBUG3
Definition: elog.h:28
bool MyDatabaseHasLoginEventTriggers
Definition: globals.c:99
int MyCancelKeyLength
Definition: globals.c:54
bool IsBinaryUpgrade
Definition: globals.c:122
Oid MyDatabaseTableSpace
Definition: globals.c:97
char MyCancelKey[MAX_CANCEL_KEY_LENGTH]
Definition: globals.c:53
struct Port * MyProcPort
Definition: globals.c:52
const char * hba_authname(UserAuth auth_method)
Definition: hba.c:3123
static char * username
Definition: initdb.c:153
#define INJECTION_POINT(name)
void LockSharedObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1082
#define RowExclusiveLock
Definition: lockdefs.h:38
void InitializeClientEncoding(void)
Definition: mbutils.c:281
void pfree(void *pointer)
Definition: mcxt.c:2152
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:477
#define INIT_PG_LOAD_SESSION_LIBS
Definition: miscadmin.h:499
#define AmAutoVacuumWorkerProcess()
Definition: miscadmin.h:383
#define AmBackgroundWorkerProcess()
Definition: miscadmin.h:384
#define AmLogicalSlotSyncWorkerProcess()
Definition: miscadmin.h:386
#define AmAutoVacuumLauncherProcess()
Definition: miscadmin.h:382
#define INIT_PG_OVERRIDE_ROLE_LOGIN
Definition: miscadmin.h:501
#define INIT_PG_OVERRIDE_ALLOW_CONNS
Definition: miscadmin.h:500
void InitializeSessionUserId(const char *rolename, Oid roleid, bool bypass_login_check)
Definition: miscinit.c:761
void InitializeSystemUser(const char *authn_id, const char *auth_method)
Definition: miscinit.c:925
void InitializeSessionUserIdStandalone(void)
Definition: miscinit.c:891
void process_session_preload_libraries(void)
Definition: miscinit.c:1916
Oid GetSessionUserId(void)
Definition: miscinit.c:559
void SetDatabasePath(const char *path)
Definition: miscinit.c:334
ClientConnectionInfo MyClientConnectionInfo
Definition: miscinit.c:1069
bool has_rolreplication(Oid roleid)
Definition: miscinit.c:739
void ValidatePgVersion(const char *path)
Definition: miscinit.c:1769
int namestrcmp(Name name, const char *str)
Definition: name.c:247
void InitializeSearchPath(void)
Definition: namespace.c:4736
#define NAMEDATALEN
void pgstat_before_server_shutdown(int code, Datum arg)
Definition: pgstat.c:559
void InitPlanCache(void)
Definition: plancache.c:147
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
void EnablePortalManager(void)
Definition: portalmem.c:104
int PostAuthDelay
Definition: postgres.c:99
static void ShutdownPostgres(int code, Datum arg)
Definition: postinit.c:1350
static void IdleInTransactionSessionTimeoutHandler(void)
Definition: postinit.c:1407
static void LockTimeoutHandler(void)
Definition: postinit.c:1389
static void IdleStatsUpdateTimeoutHandler(void)
Definition: postinit.c:1423
static void process_settings(Oid databaseid, Oid roleid)
Definition: postinit.c:1316
static void IdleSessionTimeoutHandler(void)
Definition: postinit.c:1415
static void process_startup_options(Port *port, bool am_superuser)
Definition: postinit.c:1251
static void StatementTimeoutHandler(void)
Definition: postinit.c:1367
static void CheckMyDatabase(const char *name, bool am_superuser, bool override_allow_connections)
Definition: postinit.c:323
static bool ThereIsAtLeastOneRole(void)
Definition: postinit.c:1442
static void PerformAuthentication(Port *port)
Definition: postinit.c:194
static void ClientCheckTimeoutHandler(void)
Definition: postinit.c:1431
static HeapTuple GetDatabaseTuple(const char *dbname)
Definition: postinit.c:105
static HeapTuple GetDatabaseTupleByOid(Oid dboid)
Definition: postinit.c:148
static void TransactionTimeoutHandler(void)
Definition: postinit.c:1399
int ReservedConnections
Definition: postmaster.c:230
int SuperuserReservedConnections
Definition: postmaster.c:229
short access
Definition: preproc-type.c:36
void ProcSignalInit(char *cancel_key, int cancel_key_len)
Definition: procsignal.c:165
void RelationCacheInitializePhase3(void)
Definition: relcache.c:4107
void RelationCacheInitialize(void)
Definition: relcache.c:4002
void RelationCacheInitializePhase2(void)
Definition: relcache.c:4048
char * GetDatabasePath(Oid dbOid, Oid spcOid)
Definition: relpath.c:110
void ReleaseAuxProcessResources(bool isCommit)
Definition: resowner.c:1019
ResourceOwner CurrentResourceOwner
Definition: resowner.c:173
void CreateAuxProcessResourceOwner(void)
Definition: resowner.c:999
void InitializeSession(void)
Definition: session.c:54
void pg_usleep(long microsec)
Definition: signal.c:53
void SharedInvalBackendInit(bool sendOnly)
Definition: sinvaladt.c:271
void InvalidateCatalogSnapshot(void)
Definition: snapmgr.c:443
bool HaveNFreeProcs(int n, int *nfree)
Definition: proc.c:783
void CheckDeadLockAlert(void)
Definition: proc.c:1874
void InitProcessPhase2(void)
Definition: proc.c:581
const char * authn_id
Definition: libpq-be.h:99
UserAuth auth_method
Definition: libpq-be.h:105
Oid databaseId
Definition: proc.h:216
bool superuser(void)
Definition: superuser.c:46
void InitCatalogCache(void)
Definition: syscache.c:110
TimeoutId RegisterTimeout(TimeoutId id, timeout_handler_proc handler)
Definition: timeout.c:505
@ IDLE_SESSION_TIMEOUT
Definition: timeout.h:35
@ IDLE_IN_TRANSACTION_SESSION_TIMEOUT
Definition: timeout.h:33
@ LOCK_TIMEOUT
Definition: timeout.h:28
@ STATEMENT_TIMEOUT
Definition: timeout.h:29
@ DEADLOCK_TIMEOUT
Definition: timeout.h:27
@ TRANSACTION_TIMEOUT
Definition: timeout.h:34
@ IDLE_STATS_UPDATE_TIMEOUT
Definition: timeout.h:36
@ CLIENT_CONNECTION_CHECK_TIMEOUT
Definition: timeout.h:37
bool am_walsender
Definition: walsender.c:120
bool am_db_walsender
Definition: walsender.c:123
void StartTransactionCommand(void)
Definition: xact.c:3059
int XactIsoLevel
Definition: xact.c:79
void SetCurrentStatementStartTimestamp(void)
Definition: xact.c:914
void CommitTransactionCommand(void)
Definition: xact.c:3157
#define XACT_READ_COMMITTED
Definition: xact.h:37
void StartupXLOG(void)
Definition: xlog.c:5614
void ShutdownXLOG(int code, Datum arg)
Definition: xlog.c:6790

References am_db_walsender, am_walsender, AmAutoVacuumLauncherProcess, AmAutoVacuumWorkerProcess, AmBackgroundWorkerProcess, AmLogicalSlotSyncWorkerProcess, AmRegularBackendProcess, Assert(), ClientConnectionInfo::auth_method, ClientConnectionInfo::authn_id, before_shmem_exit(), CheckDeadLockAlert(), CheckMyDatabase(), CLIENT_CONNECTION_CHECK_TIMEOUT, ClientCheckTimeoutHandler(), CommitTransactionCommand(), CreateAuxProcessResourceOwner(), CurrentResourceOwner, database_is_invalid_form(), PGPROC::databaseId, dbname, DEADLOCK_TIMEOUT, DEBUG3, elog, EnablePortalManager(), ereport, errcode(), errcode_for_file_access(), errdetail(), errhint(), errmsg(), FATAL, GetDatabasePath(), GetDatabaseTuple(), GetDatabaseTupleByOid(), GetSessionUserId(), GETSTRUCT(), GetUserId(), has_privs_of_role(), has_rolreplication(), HaveNFreeProcs(), hba_authname(), HeapTupleIsValid, IDLE_IN_TRANSACTION_SESSION_TIMEOUT, IDLE_SESSION_TIMEOUT, IDLE_STATS_UPDATE_TIMEOUT, IdleInTransactionSessionTimeoutHandler(), IdleSessionTimeoutHandler(), IdleStatsUpdateTimeoutHandler(), INIT_PG_LOAD_SESSION_LIBS, INIT_PG_OVERRIDE_ALLOW_CONNS, INIT_PG_OVERRIDE_ROLE_LOGIN, InitCatalogCache(), initialize_acl(), InitializeClientEncoding(), InitializeSearchPath(), InitializeSession(), InitializeSessionUserId(), InitializeSessionUserIdStandalone(), InitializeSystemUser(), InitPlanCache(), InitProcessPhase2(), INJECTION_POINT, InvalidateCatalogSnapshot(), IsBinaryUpgrade, IsBootstrapProcessingMode, IsUnderPostmaster, LOCK_TIMEOUT, LockSharedObject(), LockTimeoutHandler(), MyCancelKey, MyCancelKeyLength, MyClientConnectionInfo, MyDatabaseHasLoginEventTriggers, MyDatabaseId, MyDatabaseTableSpace, MyProc, MyProcPort, NAMEDATALEN, NameStr, namestrcmp(), OidIsValid, PerformAuthentication(), pfree(), pg_usleep(), pgstat_before_server_shutdown(), pgstat_beinit(), pgstat_bestart_final(), pgstat_bestart_initial(), pgstat_bestart_security(), PostAuthDelay, process_session_preload_libraries(), process_settings(), process_startup_options(), ProcSignalInit(), RegisterTimeout(), RelationCacheInitialize(), RelationCacheInitializePhase2(), RelationCacheInitializePhase3(), ReleaseAuxProcessResources(), ReservedConnections, RowExclusiveLock, SetCurrentStatementStartTimestamp(), SetDatabasePath(), SharedInvalBackendInit(), ShutdownPostgres(), ShutdownXLOG(), StartTransactionCommand(), StartupXLOG(), STATEMENT_TIMEOUT, StatementTimeoutHandler(), strlcpy(), superuser(), SuperuserReservedConnections, ThereIsAtLeastOneRole(), TRANSACTION_TIMEOUT, TransactionTimeoutHandler(), username, ValidatePgVersion(), WARNING, XACT_READ_COMMITTED, and XactIsoLevel.

Referenced by AutoVacLauncherMain(), AutoVacWorkerMain(), BackgroundWorkerInitializeConnection(), BackgroundWorkerInitializeConnectionByOid(), BootstrapModeMain(), PostgresMain(), and ReplSlotSyncWorkerMain().

◆ LockTimeoutHandler()

static void LockTimeoutHandler ( void  )
static

Definition at line 1389 of file postinit.c.

1390{
1391#ifdef HAVE_SETSID
1392 /* try to signal whole process group */
1393 kill(-MyProcPid, SIGINT);
1394#endif
1395 kill(MyProcPid, SIGINT);
1396}
int MyProcPid
Definition: globals.c:48
#define kill(pid, sig)
Definition: win32_port.h:493

References kill, and MyProcPid.

Referenced by InitPostgres().

◆ PerformAuthentication()

static void PerformAuthentication ( Port port)
static

Definition at line 194 of file postinit.c.

195{
196 /* This should be set already, but let's make sure */
197 ClientAuthInProgress = true; /* limit visibility of log messages */
198
199 /*
200 * In EXEC_BACKEND case, we didn't inherit the contents of pg_hba.conf
201 * etcetera from the postmaster, and have to load them ourselves.
202 *
203 * FIXME: [fork/exec] Ugh. Is there a way around this overhead?
204 */
205#ifdef EXEC_BACKEND
206
207 /*
208 * load_hba() and load_ident() want to work within the PostmasterContext,
209 * so create that if it doesn't exist (which it won't). We'll delete it
210 * again later, in PostgresMain.
211 */
212 if (PostmasterContext == NULL)
214 "Postmaster",
216
217 if (!load_hba())
218 {
219 /*
220 * It makes no sense to continue if we fail to load the HBA file,
221 * since there is no way to connect to the database in this case.
222 */
224 /* translator: %s is a configuration file */
225 (errmsg("could not load %s", HbaFileName)));
226 }
227
228 if (!load_ident())
229 {
230 /*
231 * It is ok to continue if we fail to load the IDENT file, although it
232 * means that you cannot log in using any of the authentication
233 * methods that need a user name mapping. load_ident() already logged
234 * the details of error to the log.
235 */
236 }
237#endif
238
239 /* Capture authentication start time for logging */
241
242 /*
243 * Set up a timeout in case a buggy or malicious client fails to respond
244 * during authentication. Since we're inside a transaction and might do
245 * database access, we have to use the statement_timeout infrastructure.
246 */
248
249 /*
250 * Now perform authentication exchange.
251 */
252 set_ps_display("authentication");
253 ClientAuthentication(port); /* might not return, if failure */
254
255 /*
256 * Done with authentication. Disable the timeout, and log if needed.
257 */
259
260 /* Capture authentication end time for logging */
262
264 {
265 StringInfoData logmsg;
266
267 initStringInfo(&logmsg);
268 if (am_walsender)
269 appendStringInfo(&logmsg, _("replication connection authorized: user=%s"),
270 port->user_name);
271 else
272 appendStringInfo(&logmsg, _("connection authorized: user=%s"),
273 port->user_name);
274 if (!am_walsender)
275 appendStringInfo(&logmsg, _(" database=%s"), port->database_name);
276
277 if (port->application_name != NULL)
278 appendStringInfo(&logmsg, _(" application_name=%s"),
279 port->application_name);
280
281#ifdef USE_SSL
282 if (port->ssl_in_use)
283 appendStringInfo(&logmsg, _(" SSL enabled (protocol=%s, cipher=%s, bits=%d)"),
287#endif
288#ifdef ENABLE_GSS
289 if (port->gss)
290 {
291 const char *princ = be_gssapi_get_princ(port);
292
293 if (princ)
294 appendStringInfo(&logmsg,
295 _(" GSS (authenticated=%s, encrypted=%s, delegated_credentials=%s, principal=%s)"),
296 be_gssapi_get_auth(port) ? _("yes") : _("no"),
297 be_gssapi_get_enc(port) ? _("yes") : _("no"),
298 be_gssapi_get_delegation(port) ? _("yes") : _("no"),
299 princ);
300 else
301 appendStringInfo(&logmsg,
302 _(" GSS (authenticated=%s, encrypted=%s, delegated_credentials=%s)"),
303 be_gssapi_get_auth(port) ? _("yes") : _("no"),
304 be_gssapi_get_enc(port) ? _("yes") : _("no"),
305 be_gssapi_get_delegation(port) ? _("yes") : _("no"));
306 }
307#endif
308
309 ereport(LOG, errmsg_internal("%s", logmsg.data));
310 pfree(logmsg.data);
311 }
312
313 set_ps_display("startup");
314
315 ClientAuthInProgress = false; /* client_min_messages is active now */
316}
void ClientAuthentication(Port *port)
Definition: auth.c:371
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1645
uint32 log_connections
ConnectionTiming conn_timing
@ LOG_CONNECTION_AUTHORIZATION
bool be_gssapi_get_auth(Port *port)
bool be_gssapi_get_enc(Port *port)
const char * be_gssapi_get_princ(Port *port)
bool be_gssapi_get_delegation(Port *port)
const char * be_tls_get_version(Port *port)
int be_tls_get_cipher_bits(Port *port)
const char * be_tls_get_cipher(Port *port)
int errmsg_internal(const char *fmt,...)
Definition: elog.c:1158
#define _(x)
Definition: elog.c:91
#define LOG
Definition: elog.h:31
char * HbaFileName
Definition: guc_tables.c:556
bool load_ident(void)
Definition: hba.c:3021
bool load_hba(void)
Definition: hba.c:2645
MemoryContext TopMemoryContext
Definition: mcxt.c:165
MemoryContext PostmasterContext
Definition: mcxt.c:167
#define AllocSetContextCreate
Definition: memutils.h:149
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:180
static int port
Definition: pg_regress.c:115
bool ClientAuthInProgress
Definition: postmaster.c:372
int AuthenticationTimeout
Definition: postmaster.c:241
static void set_ps_display(const char *activity)
Definition: ps_status.h:40
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:145
void initStringInfo(StringInfo str)
Definition: stringinfo.c:97
TimestampTz auth_start
TimestampTz auth_end
void enable_timeout_after(TimeoutId id, int delay_ms)
Definition: timeout.c:560
void disable_timeout(TimeoutId id, bool keep_indicator)
Definition: timeout.c:685

References _, ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, am_walsender, appendStringInfo(), ConnectionTiming::auth_end, ConnectionTiming::auth_start, AuthenticationTimeout, be_gssapi_get_auth(), be_gssapi_get_delegation(), be_gssapi_get_enc(), be_gssapi_get_princ(), be_tls_get_cipher(), be_tls_get_cipher_bits(), be_tls_get_version(), ClientAuthentication(), ClientAuthInProgress, conn_timing, StringInfoData::data, disable_timeout(), enable_timeout_after(), ereport, errmsg(), errmsg_internal(), FATAL, GetCurrentTimestamp(), HbaFileName, initStringInfo(), load_hba(), load_ident(), LOG, LOG_CONNECTION_AUTHORIZATION, log_connections, pfree(), port, PostmasterContext, set_ps_display(), STATEMENT_TIMEOUT, and TopMemoryContext.

Referenced by InitPostgres().

◆ pg_split_opts()

void pg_split_opts ( char **  argv,
int *  argcp,
const char *  optstr 
)

Definition at line 497 of file postinit.c.

498{
500
501 initStringInfo(&s);
502
503 while (*optstr)
504 {
505 bool last_was_escape = false;
506
507 resetStringInfo(&s);
508
509 /* skip over leading space */
510 while (isspace((unsigned char) *optstr))
511 optstr++;
512
513 if (*optstr == '\0')
514 break;
515
516 /*
517 * Parse a single option, stopping at the first space, unless it's
518 * escaped.
519 */
520 while (*optstr)
521 {
522 if (isspace((unsigned char) *optstr) && !last_was_escape)
523 break;
524
525 if (!last_was_escape && *optstr == '\\')
526 last_was_escape = true;
527 else
528 {
529 last_was_escape = false;
530 appendStringInfoChar(&s, *optstr);
531 }
532
533 optstr++;
534 }
535
536 /* now store the option in the next argv[] position */
537 argv[(*argcp)++] = pstrdup(s.data);
538 }
539
540 pfree(s.data);
541}
char * pstrdup(const char *in)
Definition: mcxt.c:2327
void resetStringInfo(StringInfo str)
Definition: stringinfo.c:126
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:242

References appendStringInfoChar(), StringInfoData::data, initStringInfo(), pfree(), pstrdup(), and resetStringInfo().

Referenced by process_startup_options().

◆ process_settings()

static void process_settings ( Oid  databaseid,
Oid  roleid 
)
static

Definition at line 1316 of file postinit.c.

1317{
1318 Relation relsetting;
1319 Snapshot snapshot;
1320
1321 if (!IsUnderPostmaster)
1322 return;
1323
1324 relsetting = table_open(DbRoleSettingRelationId, AccessShareLock);
1325
1326 /* read all the settings under the same snapshot for efficiency */
1327 snapshot = RegisterSnapshot(GetCatalogSnapshot(DbRoleSettingRelationId));
1328
1329 /* Later settings are ignored if set earlier. */
1330 ApplySetting(snapshot, databaseid, roleid, relsetting, PGC_S_DATABASE_USER);
1331 ApplySetting(snapshot, InvalidOid, roleid, relsetting, PGC_S_USER);
1332 ApplySetting(snapshot, databaseid, InvalidOid, relsetting, PGC_S_DATABASE);
1333 ApplySetting(snapshot, InvalidOid, InvalidOid, relsetting, PGC_S_GLOBAL);
1334
1335 UnregisterSnapshot(snapshot);
1336 table_close(relsetting, AccessShareLock);
1337}
@ PGC_S_GLOBAL
Definition: guc.h:118
@ PGC_S_DATABASE
Definition: guc.h:119
@ PGC_S_DATABASE_USER
Definition: guc.h:121
@ PGC_S_USER
Definition: guc.h:120
void ApplySetting(Snapshot snapshot, Oid databaseid, Oid roleid, Relation relsetting, GucSource source)
#define InvalidOid
Definition: postgres_ext.h:35
Snapshot GetCatalogSnapshot(Oid relid)
Definition: snapmgr.c:373
void UnregisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:853
Snapshot RegisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:811

References AccessShareLock, ApplySetting(), GetCatalogSnapshot(), InvalidOid, IsUnderPostmaster, PGC_S_DATABASE, PGC_S_DATABASE_USER, PGC_S_GLOBAL, PGC_S_USER, RegisterSnapshot(), table_close(), table_open(), and UnregisterSnapshot().

Referenced by InitPostgres().

◆ process_startup_options()

static void process_startup_options ( Port port,
bool  am_superuser 
)
static

Definition at line 1251 of file postinit.c.

1252{
1253 GucContext gucctx;
1254 ListCell *gucopts;
1255
1256 gucctx = am_superuser ? PGC_SU_BACKEND : PGC_BACKEND;
1257
1258 /*
1259 * First process any command-line switches that were included in the
1260 * startup packet, if we are in a regular backend.
1261 */
1262 if (port->cmdline_options != NULL)
1263 {
1264 /*
1265 * The maximum possible number of commandline arguments that could
1266 * come from port->cmdline_options is (strlen + 1) / 2; see
1267 * pg_split_opts().
1268 */
1269 char **av;
1270 int maxac;
1271 int ac;
1272
1273 maxac = 2 + (strlen(port->cmdline_options) + 1) / 2;
1274
1275 av = (char **) palloc(maxac * sizeof(char *));
1276 ac = 0;
1277
1278 av[ac++] = "postgres";
1279
1280 pg_split_opts(av, &ac, port->cmdline_options);
1281
1282 av[ac] = NULL;
1283
1284 Assert(ac < maxac);
1285
1286 (void) process_postgres_switches(ac, av, gucctx, NULL);
1287 }
1288
1289 /*
1290 * Process any additional GUC variable settings passed in startup packet.
1291 * These are handled exactly like command-line variables.
1292 */
1293 gucopts = list_head(port->guc_options);
1294 while (gucopts)
1295 {
1296 char *name;
1297 char *value;
1298
1299 name = lfirst(gucopts);
1300 gucopts = lnext(port->guc_options, gucopts);
1301
1302 value = lfirst(gucopts);
1303 gucopts = lnext(port->guc_options, gucopts);
1304
1306 }
1307}
@ PGC_S_CLIENT
Definition: guc.h:122
GucContext
Definition: guc.h:72
@ PGC_SU_BACKEND
Definition: guc.h:76
static struct @165 value
void * palloc(Size size)
Definition: mcxt.c:1945
#define lfirst(lc)
Definition: pg_list.h:172
static ListCell * list_head(const List *l)
Definition: pg_list.h:128
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:343
void process_postgres_switches(int argc, char *argv[], GucContext ctx, const char **dbname)
Definition: postgres.c:3795
void pg_split_opts(char **argv, int *argcp, const char *optstr)
Definition: postinit.c:497
struct @10::@11 av[32]

References Assert(), av, lfirst, list_head(), lnext(), name, palloc(), pg_split_opts(), PGC_BACKEND, PGC_S_CLIENT, PGC_SU_BACKEND, port, process_postgres_switches(), SetConfigOption(), and value.

Referenced by InitPostgres().

◆ ShutdownPostgres()

static void ShutdownPostgres ( int  code,
Datum  arg 
)
static

Definition at line 1350 of file postinit.c.

1351{
1352 /* Make sure we've killed any active transaction */
1354
1355 /*
1356 * User locks are not released by transaction end, so be sure to release
1357 * them explicitly.
1358 */
1360}
void LockReleaseAll(LOCKMETHODID lockmethodid, bool allLocks)
Definition: lock.c:2275
#define USER_LOCKMETHOD
Definition: lock.h:127
void AbortOutOfAnyTransaction(void)
Definition: xact.c:4862

References AbortOutOfAnyTransaction(), LockReleaseAll(), and USER_LOCKMETHOD.

Referenced by InitPostgres().

◆ StatementTimeoutHandler()

static void StatementTimeoutHandler ( void  )
static

Definition at line 1367 of file postinit.c.

1368{
1369 int sig = SIGINT;
1370
1371 /*
1372 * During authentication the timeout is used to deal with
1373 * authentication_timeout - we want to quit in response to such timeouts.
1374 */
1376 sig = SIGTERM;
1377
1378#ifdef HAVE_SETSID
1379 /* try to signal whole process group */
1380 kill(-MyProcPid, sig);
1381#endif
1382 kill(MyProcPid, sig);
1383}
static int sig
Definition: pg_ctl.c:80

References ClientAuthInProgress, kill, MyProcPid, and sig.

Referenced by InitPostgres().

◆ ThereIsAtLeastOneRole()

static bool ThereIsAtLeastOneRole ( void  )
static

Definition at line 1442 of file postinit.c.

1443{
1444 Relation pg_authid_rel;
1445 TableScanDesc scan;
1446 bool result;
1447
1448 pg_authid_rel = table_open(AuthIdRelationId, AccessShareLock);
1449
1450 scan = table_beginscan_catalog(pg_authid_rel, 0, NULL);
1451 result = (heap_getnext(scan, ForwardScanDirection) != NULL);
1452
1453 table_endscan(scan);
1454 table_close(pg_authid_rel, AccessShareLock);
1455
1456 return result;
1457}
HeapTuple heap_getnext(TableScanDesc sscan, ScanDirection direction)
Definition: heapam.c:1314
@ ForwardScanDirection
Definition: sdir.h:28
TableScanDesc table_beginscan_catalog(Relation relation, int nkeys, struct ScanKeyData *key)
Definition: tableam.c:113
static void table_endscan(TableScanDesc scan)
Definition: tableam.h:979

References AccessShareLock, ForwardScanDirection, heap_getnext(), table_beginscan_catalog(), table_close(), table_endscan(), and table_open().

Referenced by InitPostgres().

◆ TransactionTimeoutHandler()

static void TransactionTimeoutHandler ( void  )
static

Definition at line 1399 of file postinit.c.

1400{
1402 InterruptPending = true;
1404}
volatile sig_atomic_t TransactionTimeoutPending
Definition: globals.c:38

References InterruptPending, MyLatch, SetLatch(), and TransactionTimeoutPending.

Referenced by InitPostgres().