PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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/bufmgr.h"
#include "storage/fd.h"
#include "storage/ipc.h"
#include "storage/lmgr.h"
#include "storage/proc.h"
#include "storage/procarray.h"
#include "storage/procsignal.h"
#include "storage/sinvaladt.h"
#include "storage/smgr.h"
#include "storage/sync.h"
#include "tcop/tcopprot.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/guc_hooks.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 606 of file postinit.c.

607{
608 Assert(MyProc != NULL);
609
610 /*
611 * Initialize our input/output/debugging file descriptors.
612 */
614
615 /*
616 * Initialize file access. Done early so other subsystems can access
617 * files.
618 */
620
621 /*
622 * Initialize statistics reporting. This needs to happen early to ensure
623 * that pgstat's shutdown callback runs after the shutdown callbacks of
624 * all subsystems that can produce stats (like e.g. transaction commits
625 * can).
626 */
628
629 /* Do local initialization of storage and buffer managers */
630 InitSync();
631 smgrinit();
633
634 /*
635 * Initialize temporary file access after pgstat, so that the temporary
636 * file shutdown hook can report temporary file statistics.
637 */
639
640 /*
641 * Initialize local buffers for WAL record construction, in case we ever
642 * try to insert XLOG.
643 */
645
646 /* Initialize lock manager's local structs */
648
649 /*
650 * Initialize replication slots after pgstat. The exit hook might need to
651 * drop ephemeral slots, which in turn triggers stats reporting.
652 */
654}
void InitBufferManagerAccess(void)
Definition: bufmgr.c:3576
#define Assert(condition)
Definition: c.h:812
void DebugFileOpen(void)
Definition: elog.c:2111
void InitFileAccess(void)
Definition: fd.c:902
void InitTemporaryFileAccess(void)
Definition: fd.c:932
void InitLockManagerAccess(void)
Definition: lock.c:499
void pgstat_initialize(void)
Definition: pgstat.c:639
void ReplicationSlotInitialize(void)
Definition: slot.c:224
void smgrinit(void)
Definition: smgr.c:157
PGPROC * MyProc
Definition: proc.c:66
void InitSync(void)
Definition: sync.c:124
void InitXLogInsert(void)
Definition: xloginsert.c:1348

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

Referenced by 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 313 of file postinit.c.

314{
315 HeapTuple tup;
316 Form_pg_database dbform;
317 Datum datum;
318 bool isnull;
319 char *collate;
320 char *ctype;
321
322 /* Fetch our pg_database row normally, via syscache */
323 tup = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(MyDatabaseId));
324 if (!HeapTupleIsValid(tup))
325 elog(ERROR, "cache lookup failed for database %u", MyDatabaseId);
326 dbform = (Form_pg_database) GETSTRUCT(tup);
327
328 /* This recheck is strictly paranoia */
329 if (strcmp(name, NameStr(dbform->datname)) != 0)
331 (errcode(ERRCODE_UNDEFINED_DATABASE),
332 errmsg("database \"%s\" has disappeared from pg_database",
333 name),
334 errdetail("Database OID %u now seems to belong to \"%s\".",
335 MyDatabaseId, NameStr(dbform->datname))));
336
337 /*
338 * Check permissions to connect to the database.
339 *
340 * These checks are not enforced when in standalone mode, so that there is
341 * a way to recover from disabling all access to all databases, for
342 * example "UPDATE pg_database SET datallowconn = false;".
343 */
345 {
346 /*
347 * Check that the database is currently allowing connections.
348 * (Background processes can override this test and the next one by
349 * setting override_allow_connections.)
350 */
351 if (!dbform->datallowconn && !override_allow_connections)
353 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
354 errmsg("database \"%s\" is not currently accepting connections",
355 name)));
356
357 /*
358 * Check privilege to connect to the database. (The am_superuser test
359 * is redundant, but since we have the flag, might as well check it
360 * and save a few cycles.)
361 */
362 if (!am_superuser && !override_allow_connections &&
363 object_aclcheck(DatabaseRelationId, MyDatabaseId, GetUserId(),
366 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
367 errmsg("permission denied for database \"%s\"", name),
368 errdetail("User does not have CONNECT privilege.")));
369
370 /*
371 * Check connection limit for this database. We enforce the limit
372 * only for regular backends, since other process types have their own
373 * PGPROC pools.
374 *
375 * There is a race condition here --- we create our PGPROC before
376 * checking for other PGPROCs. If two backends did this at about the
377 * same time, they might both think they were over the limit, while
378 * ideally one should succeed and one fail. Getting that to work
379 * exactly seems more trouble than it is worth, however; instead we
380 * just document that the connection limit is approximate.
381 */
382 if (dbform->datconnlimit >= 0 &&
384 !am_superuser &&
385 CountDBConnections(MyDatabaseId) > dbform->datconnlimit)
387 (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
388 errmsg("too many connections for database \"%s\"",
389 name)));
390 }
391
392 /*
393 * OK, we're golden. Next to-do item is to save the encoding info out of
394 * the pg_database tuple.
395 */
396 SetDatabaseEncoding(dbform->encoding);
397 /* Record it as a GUC internal option, too */
398 SetConfigOption("server_encoding", GetDatabaseEncodingName(),
400 /* If we have no other source of client_encoding, use server encoding */
401 SetConfigOption("client_encoding", GetDatabaseEncodingName(),
403
404 /* assign locale variables */
405 datum = SysCacheGetAttrNotNull(DATABASEOID, tup, Anum_pg_database_datcollate);
406 collate = TextDatumGetCString(datum);
407 datum = SysCacheGetAttrNotNull(DATABASEOID, tup, Anum_pg_database_datctype);
408 ctype = TextDatumGetCString(datum);
409
410 if (pg_perm_setlocale(LC_COLLATE, collate) == NULL)
412 (errmsg("database locale is incompatible with operating system"),
413 errdetail("The database was initialized with LC_COLLATE \"%s\", "
414 " which is not recognized by setlocale().", collate),
415 errhint("Recreate the database with another locale or install the missing locale.")));
416
417 if (pg_perm_setlocale(LC_CTYPE, ctype) == NULL)
419 (errmsg("database locale is incompatible with operating system"),
420 errdetail("The database was initialized with LC_CTYPE \"%s\", "
421 " which is not recognized by setlocale().", ctype),
422 errhint("Recreate the database with another locale or install the missing locale.")));
423
424 if (strcmp(ctype, "C") == 0 ||
425 strcmp(ctype, "POSIX") == 0)
426 database_ctype_is_c = true;
427
429
430 /*
431 * Check collation version. See similar code in
432 * pg_newlocale_from_collation(). Note that here we warn instead of error
433 * in any case, so that we don't prevent connecting.
434 */
435 datum = SysCacheGetAttr(DATABASEOID, tup, Anum_pg_database_datcollversion,
436 &isnull);
437 if (!isnull)
438 {
439 char *actual_versionstr;
440 char *collversionstr;
441 char *locale;
442
443 collversionstr = TextDatumGetCString(datum);
444
445 if (dbform->datlocprovider == COLLPROVIDER_LIBC)
446 locale = collate;
447 else
448 {
449 datum = SysCacheGetAttrNotNull(DATABASEOID, tup, Anum_pg_database_datlocale);
451 }
452
453 actual_versionstr = get_collation_actual_version(dbform->datlocprovider, locale);
454 if (!actual_versionstr)
455 /* should not happen */
457 "database \"%s\" has no actual collation version, but a version was recorded",
458 name);
459 else if (strcmp(actual_versionstr, collversionstr) != 0)
461 (errmsg("database \"%s\" has a collation version mismatch",
462 name),
463 errdetail("The database was created using collation version %s, "
464 "but the operating system provides version %s.",
465 collversionstr, actual_versionstr),
466 errhint("Rebuild all objects in this database that use the default collation and run "
467 "ALTER DATABASE %s REFRESH COLLATION VERSION, "
468 "or build PostgreSQL with the right library version.",
470 }
471
472 ReleaseSysCache(tup);
473}
@ ACLCHECK_OK
Definition: acl.h:183
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition: aclchk.c:3810
#define TextDatumGetCString(d)
Definition: builtins.h:98
#define NameStr(name)
Definition: c.h:700
int errdetail(const char *fmt,...)
Definition: elog.c:1203
int errhint(const char *fmt,...)
Definition: elog.c:1317
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#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:119
Oid MyDatabaseId
Definition: globals.c:93
void SetConfigOption(const char *name, const char *value, GucContext context, GucSource source)
Definition: guc.c:4332
@ PGC_S_DYNAMIC_DEFAULT
Definition: guc.h:110
@ PGC_INTERNAL
Definition: guc.h:69
@ PGC_BACKEND
Definition: guc.h:73
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
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:379
Oid GetUserId(void)
Definition: miscinit.c:517
#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:1390
bool database_ctype_is_c
Definition: pg_locale.c:161
char * pg_perm_setlocale(int category, const char *locale)
Definition: pg_locale.c:223
void init_database_collation(void)
Definition: pg_locale.c:1299
uintptr_t Datum
Definition: postgres.h:64
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
int CountDBConnections(Oid databaseid)
Definition: procarray.c:3628
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:12870
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 1393 of file postinit.c.

1394{
1396 InterruptPending = true;
1398}
volatile sig_atomic_t InterruptPending
Definition: globals.c:31
struct Latch * MyLatch
Definition: globals.c:62
volatile sig_atomic_t CheckClientConnectionPending
Definition: globals.c:34
void SetLatch(Latch *latch)
Definition: latch.c:632

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

Referenced by InitPostgres().

◆ GetDatabaseTuple()

static HeapTuple GetDatabaseTuple ( const char *  dbname)
static

Definition at line 101 of file postinit.c.

102{
103 HeapTuple tuple;
104 Relation relation;
105 SysScanDesc scan;
106 ScanKeyData key[1];
107
108 /*
109 * form a scan key
110 */
111 ScanKeyInit(&key[0],
112 Anum_pg_database_datname,
113 BTEqualStrategyNumber, F_NAMEEQ,
115
116 /*
117 * Open pg_database and fetch a tuple. Force heap scan if we haven't yet
118 * built the critical shared relcache entries (i.e., we're starting up
119 * without a shared relcache cache file).
120 */
121 relation = table_open(DatabaseRelationId, AccessShareLock);
122 scan = systable_beginscan(relation, DatabaseNameIndexId,
124 NULL,
125 1, key);
126
127 tuple = systable_getnext(scan);
128
129 /* Must copy tuple before releasing buffer */
130 if (HeapTupleIsValid(tuple))
131 tuple = heap_copytuple(tuple);
132
133 /* all done */
134 systable_endscan(scan);
135 table_close(relation, AccessShareLock);
136
137 return tuple;
138}
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:606
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:513
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:387
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:778
#define AccessShareLock
Definition: lockdefs.h:36
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:350
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:50
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 144 of file postinit.c.

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

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 1369 of file postinit.c.

1370{
1372 InterruptPending = true;
1374}
volatile sig_atomic_t IdleInTransactionSessionTimeoutPending
Definition: globals.c:36

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

Referenced by InitPostgres().

◆ IdleSessionTimeoutHandler()

static void IdleSessionTimeoutHandler ( void  )
static

Definition at line 1377 of file postinit.c.

1378{
1380 InterruptPending = true;
1382}
volatile sig_atomic_t IdleSessionTimeoutPending
Definition: globals.c:38

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

Referenced by InitPostgres().

◆ IdleStatsUpdateTimeoutHandler()

static void IdleStatsUpdateTimeoutHandler ( void  )
static

Definition at line 1385 of file postinit.c.

1386{
1388 InterruptPending = true;
1390}
volatile sig_atomic_t IdleStatsUpdateTimeoutPending
Definition: globals.c:41

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

Referenced by InitPostgres().

◆ InitializeFastPathLocks()

void InitializeFastPathLocks ( void  )

Definition at line 577 of file postinit.c.

578{
579 /* Should be initialized only once. */
581
582 /* we need at least one group */
584
586 {
587 /* stop once we exceed max_locks_per_xact */
589 break;
590
592 }
593
595}
int max_locks_per_xact
Definition: lock.c:52
int FastPathLockGroupsPerBackend
Definition: lock.c:200
#define FP_LOCK_GROUPS_PER_BACKEND_MAX
Definition: proc.h:83
#define FP_LOCK_SLOTS_PER_GROUP
Definition: proc.h:84

References Assert, FastPathLockGroupsPerBackend, FP_LOCK_GROUPS_PER_BACKEND_MAX, FP_LOCK_SLOTS_PER_GROUP, and max_locks_per_xact.

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

◆ InitializeMaxBackends()

void InitializeMaxBackends ( void  )

Definition at line 545 of file postinit.c.

546{
547 Assert(MaxBackends == 0);
548
549 /* Note that this does not include "auxiliary" processes */
552
555 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
556 errmsg("too many server processes configured"),
557 errdetail("\"max_connections\" (%d) plus \"autovacuum_max_workers\" (%d) plus \"max_worker_processes\" (%d) plus \"max_wal_senders\" (%d) must be less than %d.",
561}
int autovacuum_max_workers
Definition: autovacuum.c:118
int MaxConnections
Definition: globals.c:142
int MaxBackends
Definition: globals.c:145
int max_worker_processes
Definition: globals.c:143
#define MAX_BACKENDS
Definition: postmaster.h:138
#define NUM_SPECIAL_WORKER_PROCS
Definition: proc.h:446
int max_wal_senders
Definition: walsender.c:121

References Assert, autovacuum_max_workers, 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 700 of file postinit.c.

704{
705 bool bootstrap = IsBootstrapProcessingMode();
706 bool am_superuser;
707 char *fullpath;
708 char dbname[NAMEDATALEN];
709 int nfree = 0;
710
711 elog(DEBUG3, "InitPostgres");
712
713 /*
714 * Add my PGPROC struct to the ProcArray.
715 *
716 * Once I have done this, I am visible to other backends!
717 */
719
720 /*
721 * Initialize my entry in the shared-invalidation manager's array of
722 * per-backend data.
723 */
725
727
728 /*
729 * Also set up timeout handlers needed for backend operation. We need
730 * these in every case except bootstrap.
731 */
732 if (!bootstrap)
733 {
744 }
745
746 /*
747 * If this is either a bootstrap process or a standalone backend, start up
748 * the XLOG machinery, and register to have it closed down at exit. In
749 * other cases, the startup process is responsible for starting up the
750 * XLOG machinery, and the checkpointer for closing it down.
751 */
753 {
754 /*
755 * We don't yet have an aux-process resource owner, but StartupXLOG
756 * and ShutdownXLOG will need one. Hence, create said resource owner
757 * (and register a callback to clean it up after ShutdownXLOG runs).
758 */
760
761 StartupXLOG();
762 /* Release (and warn about) any buffer pins leaked in StartupXLOG */
764 /* Reset CurrentResourceOwner to nothing for the moment */
766
767 /*
768 * Use before_shmem_exit() so that ShutdownXLOG() can rely on DSM
769 * segments etc to work (which in turn is required for pgstats).
770 */
773 }
774
775 /*
776 * Initialize the relation cache and the system catalog caches. Note that
777 * no catalog access happens here; we only set up the hashtable structure.
778 * We must do this before starting a transaction because transaction abort
779 * would try to touch these hashtables.
780 */
784
785 /* Initialize portal manager */
787
788 /* Initialize status reporting */
790
791 /*
792 * Load relcache entries for the shared system catalogs. This must create
793 * at least entries for pg_database and catalogs used for authentication.
794 */
796
797 /*
798 * Set up process-exit callback to do pre-shutdown cleanup. This is the
799 * one of the first before_shmem_exit callbacks we register; thus, this
800 * will be one the last things we do before low-level modules like the
801 * buffer manager begin to close down. We need to have this in place
802 * before we begin our first transaction --- if we fail during the
803 * initialization transaction, as is entirely possible, we need the
804 * AbortTransaction call to clean up.
805 */
807
808 /* The autovacuum launcher is done here */
810 {
811 /* report this backend in the PgBackendStatus array */
813
814 return;
815 }
816
817 /*
818 * Start a new transaction here before first access to db.
819 */
820 if (!bootstrap)
821 {
822 /* statement_timestamp must be set for timeouts to work correctly */
825
826 /*
827 * transaction_isolation will have been set to the default by the
828 * above. If the default is "serializable", and we are in hot
829 * standby, we will fail if we don't change it to something lower.
830 * Fortunately, "read committed" is plenty good enough.
831 */
833 }
834
835 /*
836 * Perform client authentication if necessary, then figure out our
837 * postgres user ID, and see if we are a superuser.
838 *
839 * In standalone mode, autovacuum worker processes and slot sync worker
840 * process, we use a fixed ID, otherwise we figure it out from the
841 * authenticated user name.
842 */
844 {
846 am_superuser = true;
847 }
848 else if (!IsUnderPostmaster)
849 {
851 am_superuser = true;
854 (errcode(ERRCODE_UNDEFINED_OBJECT),
855 errmsg("no roles are defined in this database system"),
856 errhint("You should immediately run CREATE USER \"%s\" SUPERUSER;.",
857 username != NULL ? username : "postgres")));
858 }
859 else if (AmBackgroundWorkerProcess())
860 {
861 if (username == NULL && !OidIsValid(useroid))
862 {
864 am_superuser = true;
865 }
866 else
867 {
869 (flags & INIT_PG_OVERRIDE_ROLE_LOGIN) != 0);
870 am_superuser = superuser();
871 }
872 }
873 else
874 {
875 /* normal multiuser case */
876 Assert(MyProcPort != NULL);
878 InitializeSessionUserId(username, useroid, false);
879 /* ensure that auth_method is actually valid, aka authn_id is not NULL */
883 am_superuser = superuser();
884 }
885
886 /*
887 * Binary upgrades only allowed super-user connections
888 */
889 if (IsBinaryUpgrade && !am_superuser)
890 {
892 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
893 errmsg("must be superuser to connect in binary upgrade mode")));
894 }
895
896 /*
897 * The last few regular connection slots are reserved for superusers and
898 * roles with privileges of pg_use_reserved_connections. We do not apply
899 * these limits to background processes, since they all have their own
900 * pools of PGPROC slots.
901 *
902 * Note: At this point, the new backend has already claimed a proc struct,
903 * so we must check whether the number of free slots is strictly less than
904 * the reserved connection limits.
905 */
906 if (AmRegularBackendProcess() && !am_superuser &&
909 {
912 (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
913 errmsg("remaining connection slots are reserved for roles with the %s attribute",
914 "SUPERUSER")));
915
916 if (!has_privs_of_role(GetUserId(), ROLE_PG_USE_RESERVED_CONNECTIONS))
918 (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
919 errmsg("remaining connection slots are reserved for roles with privileges of the \"%s\" role",
920 "pg_use_reserved_connections")));
921 }
922
923 /* Check replication permissions needed for walsender processes. */
924 if (am_walsender)
925 {
926 Assert(!bootstrap);
927
930 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
931 errmsg("permission denied to start WAL sender"),
932 errdetail("Only roles with the %s attribute may start a WAL sender process.",
933 "REPLICATION")));
934 }
935
936 /*
937 * If this is a plain walsender only supporting physical replication, we
938 * don't want to connect to any particular database. Just finish the
939 * backend startup by processing any options from the startup packet, and
940 * we're done.
941 */
943 {
944 /* process any options passed in the startup packet */
945 if (MyProcPort != NULL)
946 process_startup_options(MyProcPort, am_superuser);
947
948 /* Apply PostAuthDelay as soon as we've read all options */
949 if (PostAuthDelay > 0)
950 pg_usleep(PostAuthDelay * 1000000L);
951
952 /* initialize client encoding */
954
955 /* report this backend in the PgBackendStatus array */
957
958 /* close the transaction we started above */
960
961 return;
962 }
963
964 /*
965 * Set up the global variables holding database id and default tablespace.
966 * But note we won't actually try to touch the database just yet.
967 *
968 * We take a shortcut in the bootstrap case, otherwise we have to look up
969 * the db's entry in pg_database.
970 */
971 if (bootstrap)
972 {
973 dboid = Template1DbOid;
974 MyDatabaseTableSpace = DEFAULTTABLESPACE_OID;
975 }
976 else if (in_dbname != NULL)
977 {
978 HeapTuple tuple;
979 Form_pg_database dbform;
980
981 tuple = GetDatabaseTuple(in_dbname);
982 if (!HeapTupleIsValid(tuple))
984 (errcode(ERRCODE_UNDEFINED_DATABASE),
985 errmsg("database \"%s\" does not exist", in_dbname)));
986 dbform = (Form_pg_database) GETSTRUCT(tuple);
987 dboid = dbform->oid;
988 }
989 else if (!OidIsValid(dboid))
990 {
991 /*
992 * If this is a background worker not bound to any particular
993 * database, we're done now. Everything that follows only makes sense
994 * if we are bound to a specific database. We do need to close the
995 * transaction we started before returning.
996 */
997 if (!bootstrap)
998 {
1001 }
1002 return;
1003 }
1004
1005 /*
1006 * Now, take a writer's lock on the database we are trying to connect to.
1007 * If there is a concurrently running DROP DATABASE on that database, this
1008 * will block us until it finishes (and has committed its update of
1009 * pg_database).
1010 *
1011 * Note that the lock is not held long, only until the end of this startup
1012 * transaction. This is OK since we will advertise our use of the
1013 * database in the ProcArray before dropping the lock (in fact, that's the
1014 * next thing to do). Anyone trying a DROP DATABASE after this point will
1015 * see us in the array once they have the lock. Ordering is important for
1016 * this because we don't want to advertise ourselves as being in this
1017 * database until we have the lock; otherwise we create what amounts to a
1018 * deadlock with CountOtherDBBackends().
1019 *
1020 * Note: use of RowExclusiveLock here is reasonable because we envision
1021 * our session as being a concurrent writer of the database. If we had a
1022 * way of declaring a session as being guaranteed-read-only, we could use
1023 * AccessShareLock for such sessions and thereby not conflict against
1024 * CREATE DATABASE.
1025 */
1026 if (!bootstrap)
1027 LockSharedObject(DatabaseRelationId, dboid, 0, RowExclusiveLock);
1028
1029 /*
1030 * Recheck pg_database to make sure the target database hasn't gone away.
1031 * If there was a concurrent DROP DATABASE, this ensures we will die
1032 * cleanly without creating a mess.
1033 */
1034 if (!bootstrap)
1035 {
1036 HeapTuple tuple;
1037 Form_pg_database datform;
1038
1039 tuple = GetDatabaseTupleByOid(dboid);
1040 if (HeapTupleIsValid(tuple))
1041 datform = (Form_pg_database) GETSTRUCT(tuple);
1042
1043 if (!HeapTupleIsValid(tuple) ||
1044 (in_dbname && namestrcmp(&datform->datname, in_dbname)))
1045 {
1046 if (in_dbname)
1047 ereport(FATAL,
1048 (errcode(ERRCODE_UNDEFINED_DATABASE),
1049 errmsg("database \"%s\" does not exist", in_dbname),
1050 errdetail("It seems to have just been dropped or renamed.")));
1051 else
1052 ereport(FATAL,
1053 (errcode(ERRCODE_UNDEFINED_DATABASE),
1054 errmsg("database %u does not exist", dboid)));
1055 }
1056
1057 strlcpy(dbname, NameStr(datform->datname), sizeof(dbname));
1058
1059 if (database_is_invalid_form(datform))
1060 {
1061 ereport(FATAL,
1062 errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1063 errmsg("cannot connect to invalid database \"%s\"", dbname),
1064 errhint("Use DROP DATABASE to drop invalid databases."));
1065 }
1066
1067 MyDatabaseTableSpace = datform->dattablespace;
1068 MyDatabaseHasLoginEventTriggers = datform->dathasloginevt;
1069 /* pass the database name back to the caller */
1070 if (out_dbname)
1071 strcpy(out_dbname, dbname);
1072 }
1073
1074 /*
1075 * Now that we rechecked, we are certain to be connected to a database and
1076 * thus can set MyDatabaseId.
1077 *
1078 * It is important that MyDatabaseId only be set once we are sure that the
1079 * target database can no longer be concurrently dropped or renamed. For
1080 * example, without this guarantee, pgstat_update_dbstats() could create
1081 * entries for databases that were just dropped in the pgstat shutdown
1082 * callback, which could confuse other code paths like the autovacuum
1083 * scheduler.
1084 */
1085 MyDatabaseId = dboid;
1086
1087 /*
1088 * Now we can mark our PGPROC entry with the database ID.
1089 *
1090 * We assume this is an atomic store so no lock is needed; though actually
1091 * things would work fine even if it weren't atomic. Anyone searching the
1092 * ProcArray for this database's ID should hold the database lock, so they
1093 * would not be executing concurrently with this store. A process looking
1094 * for another database's ID could in theory see a chance match if it read
1095 * a partially-updated databaseId value; but as long as all such searches
1096 * wait and retry, as in CountOtherDBBackends(), they will certainly see
1097 * the correct value on their next try.
1098 */
1100
1101 /*
1102 * We established a catalog snapshot while reading pg_authid and/or
1103 * pg_database; but until we have set up MyDatabaseId, we won't react to
1104 * incoming sinval messages for unshared catalogs, so we won't realize it
1105 * if the snapshot has been invalidated. Assume it's no good anymore.
1106 */
1108
1109 /*
1110 * Now we should be able to access the database directory safely. Verify
1111 * it's there and looks reasonable.
1112 */
1114
1115 if (!bootstrap)
1116 {
1117 if (access(fullpath, F_OK) == -1)
1118 {
1119 if (errno == ENOENT)
1120 ereport(FATAL,
1121 (errcode(ERRCODE_UNDEFINED_DATABASE),
1122 errmsg("database \"%s\" does not exist",
1123 dbname),
1124 errdetail("The database subdirectory \"%s\" is missing.",
1125 fullpath)));
1126 else
1127 ereport(FATAL,
1129 errmsg("could not access directory \"%s\": %m",
1130 fullpath)));
1131 }
1132
1133 ValidatePgVersion(fullpath);
1134 }
1135
1136 SetDatabasePath(fullpath);
1137 pfree(fullpath);
1138
1139 /*
1140 * It's now possible to do real access to the system catalogs.
1141 *
1142 * Load relcache entries for the system catalogs. This must create at
1143 * least the minimum set of "nailed-in" cache entries.
1144 */
1146
1147 /* set up ACL framework (so CheckMyDatabase can check permissions) */
1149
1150 /*
1151 * Re-read the pg_database row for our database, check permissions and set
1152 * up database-specific GUC settings. We can't do this until all the
1153 * database-access infrastructure is up. (Also, it wants to know if the
1154 * user is a superuser, so the above stuff has to happen first.)
1155 */
1156 if (!bootstrap)
1157 CheckMyDatabase(dbname, am_superuser,
1158 (flags & INIT_PG_OVERRIDE_ALLOW_CONNS) != 0);
1159
1160 /*
1161 * Now process any command-line switches and any additional GUC variable
1162 * settings passed in the startup packet. We couldn't do this before
1163 * because we didn't know if client is a superuser.
1164 */
1165 if (MyProcPort != NULL)
1166 process_startup_options(MyProcPort, am_superuser);
1167
1168 /* Process pg_db_role_setting options */
1170
1171 /* Apply PostAuthDelay as soon as we've read all options */
1172 if (PostAuthDelay > 0)
1173 pg_usleep(PostAuthDelay * 1000000L);
1174
1175 /*
1176 * Initialize various default states that can't be set up until we've
1177 * selected the active user and gotten the right GUC settings.
1178 */
1179
1180 /* set default namespace search path */
1182
1183 /* initialize client encoding */
1185
1186 /* Initialize this backend's session state. */
1188
1189 /*
1190 * If this is an interactive session, load any libraries that should be
1191 * preloaded at backend start. Since those are determined by GUCs, this
1192 * can't happen until GUC settings are complete, but we want it to happen
1193 * during the initial transaction in case anything that requires database
1194 * access needs to be done.
1195 */
1196 if ((flags & INIT_PG_LOAD_SESSION_LIBS) != 0)
1198
1199 /* report this backend in the PgBackendStatus array */
1200 if (!bootstrap)
1202
1203 /* close the transaction we started above */
1204 if (!bootstrap)
1206}
void initialize_acl(void)
Definition: acl.c:5024
bool has_privs_of_role(Oid member, Oid role)
Definition: acl.c:5268
void pgstat_beinit(void)
void pgstat_bestart(void)
#define OidIsValid(objectId)
Definition: c.h:729
bool database_is_invalid_form(Form_pg_database datform)
Definition: dbcommands.c:3211
int errcode_for_file_access(void)
Definition: elog.c:876
#define DEBUG3
Definition: elog.h:28
bool MyDatabaseHasLoginEventTriggers
Definition: globals.c:97
bool IsBinaryUpgrade
Definition: globals.c:120
int32 MyCancelKey
Definition: globals.c:52
Oid MyDatabaseTableSpace
Definition: globals.c:95
bool MyCancelKeyValid
Definition: globals.c:51
struct Port * MyProcPort
Definition: globals.c:50
const char * hba_authname(UserAuth auth_method)
Definition: hba.c:3065
static char * username
Definition: initdb.c:153
void before_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:337
void LockSharedObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1072
#define RowExclusiveLock
Definition: lockdefs.h:38
void InitializeClientEncoding(void)
Definition: mbutils.c:281
void pfree(void *pointer)
Definition: mcxt.c:1521
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:466
#define INIT_PG_LOAD_SESSION_LIBS
Definition: miscadmin.h:488
#define AmAutoVacuumWorkerProcess()
Definition: miscadmin.h:381
#define AmBackgroundWorkerProcess()
Definition: miscadmin.h:382
#define AmLogicalSlotSyncWorkerProcess()
Definition: miscadmin.h:384
#define AmAutoVacuumLauncherProcess()
Definition: miscadmin.h:380
#define INIT_PG_OVERRIDE_ROLE_LOGIN
Definition: miscadmin.h:490
#define INIT_PG_OVERRIDE_ALLOW_CONNS
Definition: miscadmin.h:489
void InitializeSessionUserId(const char *rolename, Oid roleid, bool bypass_login_check)
Definition: miscinit.c:758
void InitializeSystemUser(const char *authn_id, const char *auth_method)
Definition: miscinit.c:922
void InitializeSessionUserIdStandalone(void)
Definition: miscinit.c:888
void process_session_preload_libraries(void)
Definition: miscinit.c:1913
Oid GetSessionUserId(void)
Definition: miscinit.c:556
void SetDatabasePath(const char *path)
Definition: miscinit.c:331
ClientConnectionInfo MyClientConnectionInfo
Definition: miscinit.c:1066
bool has_rolreplication(Oid roleid)
Definition: miscinit.c:736
void ValidatePgVersion(const char *path)
Definition: miscinit.c:1766
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:560
void InitPlanCache(void)
Definition: plancache.c:155
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:98
static void ShutdownPostgres(int code, Datum arg)
Definition: postinit.c:1312
static void IdleInTransactionSessionTimeoutHandler(void)
Definition: postinit.c:1369
static void LockTimeoutHandler(void)
Definition: postinit.c:1351
static void IdleStatsUpdateTimeoutHandler(void)
Definition: postinit.c:1385
static void process_settings(Oid databaseid, Oid roleid)
Definition: postinit.c:1278
static void IdleSessionTimeoutHandler(void)
Definition: postinit.c:1377
static void process_startup_options(Port *port, bool am_superuser)
Definition: postinit.c:1213
static void StatementTimeoutHandler(void)
Definition: postinit.c:1329
static void CheckMyDatabase(const char *name, bool am_superuser, bool override_allow_connections)
Definition: postinit.c:313
static bool ThereIsAtLeastOneRole(void)
Definition: postinit.c:1404
static void PerformAuthentication(Port *port)
Definition: postinit.c:190
static void ClientCheckTimeoutHandler(void)
Definition: postinit.c:1393
static HeapTuple GetDatabaseTuple(const char *dbname)
Definition: postinit.c:101
static HeapTuple GetDatabaseTupleByOid(Oid dboid)
Definition: postinit.c:144
static void TransactionTimeoutHandler(void)
Definition: postinit.c:1361
int ReservedConnections
Definition: postmaster.c:222
int SuperuserReservedConnections
Definition: postmaster.c:221
short access
Definition: preproc-type.c:36
void ProcSignalInit(bool cancel_key_valid, int32 cancel_key)
Definition: procsignal.c:166
void RelationCacheInitializePhase3(void)
Definition: relcache.c:4051
void RelationCacheInitialize(void)
Definition: relcache.c:3946
void RelationCacheInitializePhase2(void)
Definition: relcache.c:3992
char * GetDatabasePath(Oid dbOid, Oid spcOid)
Definition: relpath.c:110
void ReleaseAuxProcessResources(bool isCommit)
Definition: resowner.c:1002
ResourceOwner CurrentResourceOwner
Definition: resowner.c:165
void CreateAuxProcessResourceOwner(void)
Definition: resowner.c:982
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:384
bool HaveNFreeProcs(int n, int *nfree)
Definition: proc.c:733
void CheckDeadLockAlert(void)
Definition: proc.c:1870
void InitProcessPhase2(void)
Definition: proc.c:531
const char * authn_id
Definition: libpq-be.h:103
UserAuth auth_method
Definition: libpq-be.h:109
Oid databaseId
Definition: proc.h:207
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:115
bool am_db_walsender
Definition: walsender.c:118
void StartTransactionCommand(void)
Definition: xact.c:3051
int XactIsoLevel
Definition: xact.c:78
void SetCurrentStatementStartTimestamp(void)
Definition: xact.c:913
void CommitTransactionCommand(void)
Definition: xact.c:3149
#define XACT_READ_COMMITTED
Definition: xact.h:37
void StartupXLOG(void)
Definition: xlog.c:5429
void ShutdownXLOG(int code, Datum arg)
Definition: xlog.c:6602

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(), InvalidateCatalogSnapshot(), IsBinaryUpgrade, IsBootstrapProcessingMode, IsUnderPostmaster, LOCK_TIMEOUT, LockSharedObject(), LockTimeoutHandler(), MyCancelKey, MyCancelKeyValid, MyClientConnectionInfo, MyDatabaseHasLoginEventTriggers, MyDatabaseId, MyDatabaseTableSpace, MyProc, MyProcPort, NAMEDATALEN, NameStr, namestrcmp(), OidIsValid, PerformAuthentication(), pfree(), pg_usleep(), pgstat_before_server_shutdown(), pgstat_beinit(), pgstat_bestart(), 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 AutoVacWorkerMain(), BackgroundWorkerInitializeConnection(), BackgroundWorkerInitializeConnectionByOid(), BootstrapModeMain(), PostgresMain(), and ReplSlotSyncWorkerMain().

◆ LockTimeoutHandler()

static void LockTimeoutHandler ( void  )
static

Definition at line 1351 of file postinit.c.

1352{
1353#ifdef HAVE_SETSID
1354 /* try to signal whole process group */
1355 kill(-MyProcPid, SIGINT);
1356#endif
1357 kill(MyProcPid, SIGINT);
1358}
int MyProcPid
Definition: globals.c:46
#define kill(pid, sig)
Definition: win32_port.h:503

References kill, and MyProcPid.

Referenced by InitPostgres().

◆ PerformAuthentication()

static void PerformAuthentication ( Port port)
static

Definition at line 190 of file postinit.c.

191{
192 /* This should be set already, but let's make sure */
193 ClientAuthInProgress = true; /* limit visibility of log messages */
194
195 /*
196 * In EXEC_BACKEND case, we didn't inherit the contents of pg_hba.conf
197 * etcetera from the postmaster, and have to load them ourselves.
198 *
199 * FIXME: [fork/exec] Ugh. Is there a way around this overhead?
200 */
201#ifdef EXEC_BACKEND
202
203 /*
204 * load_hba() and load_ident() want to work within the PostmasterContext,
205 * so create that if it doesn't exist (which it won't). We'll delete it
206 * again later, in PostgresMain.
207 */
208 if (PostmasterContext == NULL)
210 "Postmaster",
212
213 if (!load_hba())
214 {
215 /*
216 * It makes no sense to continue if we fail to load the HBA file,
217 * since there is no way to connect to the database in this case.
218 */
220 /* translator: %s is a configuration file */
221 (errmsg("could not load %s", HbaFileName)));
222 }
223
224 if (!load_ident())
225 {
226 /*
227 * It is ok to continue if we fail to load the IDENT file, although it
228 * means that you cannot log in using any of the authentication
229 * methods that need a user name mapping. load_ident() already logged
230 * the details of error to the log.
231 */
232 }
233#endif
234
235 /*
236 * Set up a timeout in case a buggy or malicious client fails to respond
237 * during authentication. Since we're inside a transaction and might do
238 * database access, we have to use the statement_timeout infrastructure.
239 */
241
242 /*
243 * Now perform authentication exchange.
244 */
245 set_ps_display("authentication");
246 ClientAuthentication(port); /* might not return, if failure */
247
248 /*
249 * Done with authentication. Disable the timeout, and log if needed.
250 */
252
253 if (Log_connections)
254 {
255 StringInfoData logmsg;
256
257 initStringInfo(&logmsg);
258 if (am_walsender)
259 appendStringInfo(&logmsg, _("replication connection authorized: user=%s"),
260 port->user_name);
261 else
262 appendStringInfo(&logmsg, _("connection authorized: user=%s"),
263 port->user_name);
264 if (!am_walsender)
265 appendStringInfo(&logmsg, _(" database=%s"), port->database_name);
266
267 if (port->application_name != NULL)
268 appendStringInfo(&logmsg, _(" application_name=%s"),
269 port->application_name);
270
271#ifdef USE_SSL
272 if (port->ssl_in_use)
273 appendStringInfo(&logmsg, _(" SSL enabled (protocol=%s, cipher=%s, bits=%d)"),
277#endif
278#ifdef ENABLE_GSS
279 if (port->gss)
280 {
281 const char *princ = be_gssapi_get_princ(port);
282
283 if (princ)
284 appendStringInfo(&logmsg,
285 _(" GSS (authenticated=%s, encrypted=%s, delegated_credentials=%s, principal=%s)"),
286 be_gssapi_get_auth(port) ? _("yes") : _("no"),
287 be_gssapi_get_enc(port) ? _("yes") : _("no"),
288 be_gssapi_get_delegation(port) ? _("yes") : _("no"),
289 princ);
290 else
291 appendStringInfo(&logmsg,
292 _(" GSS (authenticated=%s, encrypted=%s, delegated_credentials=%s)"),
293 be_gssapi_get_auth(port) ? _("yes") : _("no"),
294 be_gssapi_get_enc(port) ? _("yes") : _("no"),
295 be_gssapi_get_delegation(port) ? _("yes") : _("no"));
296 }
297#endif
298
299 ereport(LOG, errmsg_internal("%s", logmsg.data));
300 pfree(logmsg.data);
301 }
302
303 set_ps_display("startup");
304
305 ClientAuthInProgress = false; /* client_min_messages is active now */
306}
void ClientAuthentication(Port *port)
Definition: auth.c:382
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:1157
#define _(x)
Definition: elog.c:90
#define LOG
Definition: elog.h:31
char * HbaFileName
Definition: guc_tables.c:539
bool load_ident(void)
Definition: hba.c:2963
bool load_hba(void)
Definition: hba.c:2587
MemoryContext TopMemoryContext
Definition: mcxt.c:149
MemoryContext PostmasterContext
Definition: mcxt.c:151
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
static int port
Definition: pg_regress.c:115
bool Log_connections
Definition: postmaster.c:236
bool ClientAuthInProgress
Definition: postmaster.c:355
int AuthenticationTimeout
Definition: postmaster.c:233
static void set_ps_display(const char *activity)
Definition: ps_status.h:40
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:94
void initStringInfo(StringInfo str)
Definition: stringinfo.c:56
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(), 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, StringInfoData::data, disable_timeout(), enable_timeout_after(), ereport, errmsg(), errmsg_internal(), FATAL, HbaFileName, initStringInfo(), load_hba(), load_ident(), LOG, 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 487 of file postinit.c.

488{
490
491 initStringInfo(&s);
492
493 while (*optstr)
494 {
495 bool last_was_escape = false;
496
497 resetStringInfo(&s);
498
499 /* skip over leading space */
500 while (isspace((unsigned char) *optstr))
501 optstr++;
502
503 if (*optstr == '\0')
504 break;
505
506 /*
507 * Parse a single option, stopping at the first space, unless it's
508 * escaped.
509 */
510 while (*optstr)
511 {
512 if (isspace((unsigned char) *optstr) && !last_was_escape)
513 break;
514
515 if (!last_was_escape && *optstr == '\\')
516 last_was_escape = true;
517 else
518 {
519 last_was_escape = false;
520 appendStringInfoChar(&s, *optstr);
521 }
522
523 optstr++;
524 }
525
526 /* now store the option in the next argv[] position */
527 argv[(*argcp)++] = pstrdup(s.data);
528 }
529
530 pfree(s.data);
531}
char * pstrdup(const char *in)
Definition: mcxt.c:1696
void resetStringInfo(StringInfo str)
Definition: stringinfo.c:75
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:191

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 1278 of file postinit.c.

1279{
1280 Relation relsetting;
1281 Snapshot snapshot;
1282
1283 if (!IsUnderPostmaster)
1284 return;
1285
1286 relsetting = table_open(DbRoleSettingRelationId, AccessShareLock);
1287
1288 /* read all the settings under the same snapshot for efficiency */
1289 snapshot = RegisterSnapshot(GetCatalogSnapshot(DbRoleSettingRelationId));
1290
1291 /* Later settings are ignored if set earlier. */
1292 ApplySetting(snapshot, databaseid, roleid, relsetting, PGC_S_DATABASE_USER);
1293 ApplySetting(snapshot, InvalidOid, roleid, relsetting, PGC_S_USER);
1294 ApplySetting(snapshot, databaseid, InvalidOid, relsetting, PGC_S_DATABASE);
1295 ApplySetting(snapshot, InvalidOid, InvalidOid, relsetting, PGC_S_GLOBAL);
1296
1297 UnregisterSnapshot(snapshot);
1298 table_close(relsetting, AccessShareLock);
1299}
@ PGC_S_GLOBAL
Definition: guc.h:114
@ PGC_S_DATABASE
Definition: guc.h:115
@ PGC_S_DATABASE_USER
Definition: guc.h:117
@ PGC_S_USER
Definition: guc.h:116
void ApplySetting(Snapshot snapshot, Oid databaseid, Oid roleid, Relation relsetting, GucSource source)
#define InvalidOid
Definition: postgres_ext.h:36
Snapshot GetCatalogSnapshot(Oid relid)
Definition: snapmgr.c:314
void UnregisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:794
Snapshot RegisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:752

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 1213 of file postinit.c.

1214{
1215 GucContext gucctx;
1216 ListCell *gucopts;
1217
1218 gucctx = am_superuser ? PGC_SU_BACKEND : PGC_BACKEND;
1219
1220 /*
1221 * First process any command-line switches that were included in the
1222 * startup packet, if we are in a regular backend.
1223 */
1224 if (port->cmdline_options != NULL)
1225 {
1226 /*
1227 * The maximum possible number of commandline arguments that could
1228 * come from port->cmdline_options is (strlen + 1) / 2; see
1229 * pg_split_opts().
1230 */
1231 char **av;
1232 int maxac;
1233 int ac;
1234
1235 maxac = 2 + (strlen(port->cmdline_options) + 1) / 2;
1236
1237 av = (char **) palloc(maxac * sizeof(char *));
1238 ac = 0;
1239
1240 av[ac++] = "postgres";
1241
1242 pg_split_opts(av, &ac, port->cmdline_options);
1243
1244 av[ac] = NULL;
1245
1246 Assert(ac < maxac);
1247
1248 (void) process_postgres_switches(ac, av, gucctx, NULL);
1249 }
1250
1251 /*
1252 * Process any additional GUC variable settings passed in startup packet.
1253 * These are handled exactly like command-line variables.
1254 */
1255 gucopts = list_head(port->guc_options);
1256 while (gucopts)
1257 {
1258 char *name;
1259 char *value;
1260
1261 name = lfirst(gucopts);
1262 gucopts = lnext(port->guc_options, gucopts);
1263
1264 value = lfirst(gucopts);
1265 gucopts = lnext(port->guc_options, gucopts);
1266
1268 }
1269}
@ PGC_S_CLIENT
Definition: guc.h:118
GucContext
Definition: guc.h:68
@ PGC_SU_BACKEND
Definition: guc.h:72
static struct @161 value
void * palloc(Size size)
Definition: mcxt.c:1317
#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:3752
void pg_split_opts(char **argv, int *argcp, const char *optstr)
Definition: postinit.c:487
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 1312 of file postinit.c.

1313{
1314 /* Make sure we've killed any active transaction */
1316
1317 /*
1318 * User locks are not released by transaction end, so be sure to release
1319 * them explicitly.
1320 */
1322}
void LockReleaseAll(LOCKMETHODID lockmethodid, bool allLocks)
Definition: lock.c:2216
#define USER_LOCKMETHOD
Definition: lock.h:126
void AbortOutOfAnyTransaction(void)
Definition: xact.c:4854

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

Referenced by InitPostgres().

◆ StatementTimeoutHandler()

static void StatementTimeoutHandler ( void  )
static

Definition at line 1329 of file postinit.c.

1330{
1331 int sig = SIGINT;
1332
1333 /*
1334 * During authentication the timeout is used to deal with
1335 * authentication_timeout - we want to quit in response to such timeouts.
1336 */
1338 sig = SIGTERM;
1339
1340#ifdef HAVE_SETSID
1341 /* try to signal whole process group */
1342 kill(-MyProcPid, sig);
1343#endif
1344 kill(MyProcPid, sig);
1345}
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 1404 of file postinit.c.

1405{
1406 Relation pg_authid_rel;
1407 TableScanDesc scan;
1408 bool result;
1409
1410 pg_authid_rel = table_open(AuthIdRelationId, AccessShareLock);
1411
1412 scan = table_beginscan_catalog(pg_authid_rel, 0, NULL);
1413 result = (heap_getnext(scan, ForwardScanDirection) != NULL);
1414
1415 table_endscan(scan);
1416 table_close(pg_authid_rel, AccessShareLock);
1417
1418 return result;
1419}
HeapTuple heap_getnext(TableScanDesc sscan, ScanDirection direction)
Definition: heapam.c:1246
@ ForwardScanDirection
Definition: sdir.h:28
TableScanDesc table_beginscan_catalog(Relation relation, int nkeys, struct ScanKeyData *key)
Definition: tableam.c:112
static void table_endscan(TableScanDesc scan)
Definition: tableam.h:1024

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 1361 of file postinit.c.

1362{
1364 InterruptPending = true;
1366}
volatile sig_atomic_t TransactionTimeoutPending
Definition: globals.c:37

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

Referenced by InitPostgres().