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

603 {
604  Assert(MyProc != NULL);
605 
606  /*
607  * Initialize our input/output/debugging file descriptors.
608  */
609  DebugFileOpen();
610 
611  /*
612  * Initialize file access. Done early so other subsystems can access
613  * files.
614  */
615  InitFileAccess();
616 
617  /*
618  * Initialize statistics reporting. This needs to happen early to ensure
619  * that pgstat's shutdown callback runs after the shutdown callbacks of
620  * all subsystems that can produce stats (like e.g. transaction commits
621  * can).
622  */
624 
625  /* Do local initialization of storage and buffer managers */
626  InitSync();
627  smgrinit();
629 
630  /*
631  * Initialize temporary file access after pgstat, so that the temporary
632  * file shutdown hook can report temporary file statistics.
633  */
635 
636  /*
637  * Initialize local buffers for WAL record construction, in case we ever
638  * try to insert XLOG.
639  */
640  InitXLogInsert();
641 
642  /*
643  * Initialize replication slots after pgstat. The exit hook might need to
644  * drop ephemeral slots, which in turn triggers stats reporting.
645  */
647 }
void InitBufferPoolAccess(void)
Definition: bufmgr.c:3588
#define Assert(condition)
Definition: c.h:858
void DebugFileOpen(void)
Definition: elog.c:2091
void InitFileAccess(void)
Definition: fd.c:903
void InitTemporaryFileAccess(void)
Definition: fd.c:933
void pgstat_initialize(void)
Definition: pgstat.c:580
void ReplicationSlotInitialize(void)
Definition: slot.c:224
void smgrinit(void)
Definition: smgr.c:154
PGPROC * MyProc
Definition: proc.c:66
void InitSync(void)
Definition: sync.c:124
void InitXLogInsert(void)
Definition: xloginsert.c:1348

References Assert, DebugFileOpen(), InitBufferPoolAccess(), InitFileAccess(), 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  char *datlocale;
322 
323  /* Fetch our pg_database row normally, via syscache */
324  tup = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(MyDatabaseId));
325  if (!HeapTupleIsValid(tup))
326  elog(ERROR, "cache lookup failed for database %u", MyDatabaseId);
327  dbform = (Form_pg_database) GETSTRUCT(tup);
328 
329  /* This recheck is strictly paranoia */
330  if (strcmp(name, NameStr(dbform->datname)) != 0)
331  ereport(FATAL,
332  (errcode(ERRCODE_UNDEFINED_DATABASE),
333  errmsg("database \"%s\" has disappeared from pg_database",
334  name),
335  errdetail("Database OID %u now seems to belong to \"%s\".",
336  MyDatabaseId, NameStr(dbform->datname))));
337 
338  /*
339  * Check permissions to connect to the database.
340  *
341  * These checks are not enforced when in standalone mode, so that there is
342  * a way to recover from disabling all access to all databases, for
343  * example "UPDATE pg_database SET datallowconn = false;".
344  *
345  * We do not enforce them for autovacuum worker processes either.
346  */
348  {
349  /*
350  * Check that the database is currently allowing connections.
351  */
352  if (!dbform->datallowconn && !override_allow_connections)
353  ereport(FATAL,
354  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
355  errmsg("database \"%s\" is not currently accepting connections",
356  name)));
357 
358  /*
359  * Check privilege to connect to the database. (The am_superuser test
360  * is redundant, but since we have the flag, might as well check it
361  * and save a few cycles.)
362  */
363  if (!am_superuser &&
364  object_aclcheck(DatabaseRelationId, MyDatabaseId, GetUserId(),
366  ereport(FATAL,
367  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
368  errmsg("permission denied for database \"%s\"", name),
369  errdetail("User does not have CONNECT privilege.")));
370 
371  /*
372  * Check connection limit for this database.
373  *
374  * There is a race condition here --- we create our PGPROC before
375  * checking for other PGPROCs. If two backends did this at about the
376  * same time, they might both think they were over the limit, while
377  * ideally one should succeed and one fail. Getting that to work
378  * exactly seems more trouble than it is worth, however; instead we
379  * just document that the connection limit is approximate.
380  */
381  if (dbform->datconnlimit >= 0 &&
382  !am_superuser &&
383  CountDBConnections(MyDatabaseId) > dbform->datconnlimit)
384  ereport(FATAL,
385  (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
386  errmsg("too many connections for database \"%s\"",
387  name)));
388  }
389 
390  /*
391  * OK, we're golden. Next to-do item is to save the encoding info out of
392  * the pg_database tuple.
393  */
394  SetDatabaseEncoding(dbform->encoding);
395  /* Record it as a GUC internal option, too */
396  SetConfigOption("server_encoding", GetDatabaseEncodingName(),
398  /* If we have no other source of client_encoding, use server encoding */
399  SetConfigOption("client_encoding", GetDatabaseEncodingName(),
401 
402  /* assign locale variables */
403  datum = SysCacheGetAttrNotNull(DATABASEOID, tup, Anum_pg_database_datcollate);
404  collate = TextDatumGetCString(datum);
405  datum = SysCacheGetAttrNotNull(DATABASEOID, tup, Anum_pg_database_datctype);
406  ctype = TextDatumGetCString(datum);
407 
408  if (pg_perm_setlocale(LC_COLLATE, collate) == NULL)
409  ereport(FATAL,
410  (errmsg("database locale is incompatible with operating system"),
411  errdetail("The database was initialized with LC_COLLATE \"%s\", "
412  " which is not recognized by setlocale().", collate),
413  errhint("Recreate the database with another locale or install the missing locale.")));
414 
415  if (pg_perm_setlocale(LC_CTYPE, ctype) == NULL)
416  ereport(FATAL,
417  (errmsg("database locale is incompatible with operating system"),
418  errdetail("The database was initialized with LC_CTYPE \"%s\", "
419  " which is not recognized by setlocale().", ctype),
420  errhint("Recreate the database with another locale or install the missing locale.")));
421 
422  if (strcmp(ctype, "C") == 0 ||
423  strcmp(ctype, "POSIX") == 0)
424  database_ctype_is_c = true;
425 
426  if (dbform->datlocprovider == COLLPROVIDER_BUILTIN)
427  {
428  datum = SysCacheGetAttrNotNull(DATABASEOID, tup, Anum_pg_database_datlocale);
430 
431  builtin_validate_locale(dbform->encoding, datlocale);
432 
435  }
436  else if (dbform->datlocprovider == COLLPROVIDER_ICU)
437  {
438  char *icurules;
439 
440  datum = SysCacheGetAttrNotNull(DATABASEOID, tup, Anum_pg_database_datlocale);
442 
443  datum = SysCacheGetAttr(DATABASEOID, tup, Anum_pg_database_daticurules, &isnull);
444  if (!isnull)
445  icurules = TextDatumGetCString(datum);
446  else
447  icurules = NULL;
448 
450  }
451  else
452  datlocale = NULL;
453 
454  default_locale.provider = dbform->datlocprovider;
455 
456  /*
457  * Default locale is currently always deterministic. Nondeterministic
458  * locales currently don't support pattern matching, which would break a
459  * lot of things if applied globally.
460  */
462 
463  /*
464  * Check collation version. See similar code in
465  * pg_newlocale_from_collation(). Note that here we warn instead of error
466  * in any case, so that we don't prevent connecting.
467  */
468  datum = SysCacheGetAttr(DATABASEOID, tup, Anum_pg_database_datcollversion,
469  &isnull);
470  if (!isnull)
471  {
472  char *actual_versionstr;
473  char *collversionstr;
474  char *locale;
475 
476  collversionstr = TextDatumGetCString(datum);
477 
478  if (dbform->datlocprovider == COLLPROVIDER_LIBC)
479  locale = collate;
480  else
481  locale = datlocale;
482 
483  actual_versionstr = get_collation_actual_version(dbform->datlocprovider, locale);
484  if (!actual_versionstr)
485  /* should not happen */
486  elog(WARNING,
487  "database \"%s\" has no actual collation version, but a version was recorded",
488  name);
489  else if (strcmp(actual_versionstr, collversionstr) != 0)
491  (errmsg("database \"%s\" has a collation version mismatch",
492  name),
493  errdetail("The database was created using collation version %s, "
494  "but the operating system provides version %s.",
495  collversionstr, actual_versionstr),
496  errhint("Rebuild all objects in this database that use the default collation and run "
497  "ALTER DATABASE %s REFRESH COLLATION VERSION, "
498  "or build PostgreSQL with the right library version.",
500  }
501 
502  ReleaseSysCache(tup);
503 }
@ ACLCHECK_OK
Definition: acl.h:183
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition: aclchk.c:3888
#define TextDatumGetCString(d)
Definition: builtins.h:98
#define NameStr(name)
Definition: c.h:746
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:224
#define ereport(elevel,...)
Definition: elog.h:149
bool IsUnderPostmaster
Definition: globals.c:118
Oid MyDatabaseId
Definition: globals.c:92
void SetConfigOption(const char *name, const char *value, GucContext context, GucSource source)
Definition: guc.c:4282
@ 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 * datlocale
Definition: initdb.c:149
static char * locale
Definition: initdb.c:140
const char * GetDatabaseEncodingName(void)
Definition: mbutils.c:1267
void SetDatabaseEncoding(int encoding)
Definition: mbutils.c:1161
MemoryContext TopMemoryContext
Definition: mcxt.c:149
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1683
#define AmAutoVacuumWorkerProcess()
Definition: miscadmin.h:375
Oid GetUserId(void)
Definition: miscinit.c:514
#define ACL_CONNECT
Definition: parsenodes.h:87
FormData_pg_database * Form_pg_database
Definition: pg_database.h:96
void make_icu_collator(const char *iculocstr, const char *icurules, struct pg_locale_struct *resultp)
Definition: pg_locale.c:1449
struct pg_locale_struct default_locale
Definition: pg_locale.c:1446
bool database_ctype_is_c
Definition: pg_locale.c:117
char * get_collation_actual_version(char collprovider, const char *collcollate)
Definition: pg_locale.c:1730
char * pg_perm_setlocale(int category, const char *locale)
Definition: pg_locale.c:212
const char * builtin_validate_locale(int encoding, const char *locale)
Definition: pg_locale.c:2546
uintptr_t Datum
Definition: postgres.h:64
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
int CountDBConnections(Oid databaseid)
Definition: procarray.c:3633
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:12596
struct pg_locale_struct::@151::@152 builtin
union pg_locale_struct::@151 info
bool deterministic
Definition: pg_locale.h:76
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:266
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:218
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:479
Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition: syscache.c:510
const char * name

References ACL_CONNECT, ACLCHECK_OK, AmAutoVacuumWorkerProcess, pg_locale_struct::builtin, builtin_validate_locale(), CountDBConnections(), database_ctype_is_c, datlocale, default_locale, pg_locale_struct::deterministic, elog, ereport, errcode(), errdetail(), errhint(), errmsg(), ERROR, FATAL, get_collation_actual_version(), GetDatabaseEncodingName(), GETSTRUCT, GetUserId(), HeapTupleIsValid, pg_locale_struct::info, IsUnderPostmaster, locale, make_icu_collator(), MemoryContextStrdup(), MyDatabaseId, name, NameStr, object_aclcheck(), ObjectIdGetDatum(), pg_perm_setlocale(), PGC_BACKEND, PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT, pg_locale_struct::provider, quote_identifier(), ReleaseSysCache(), SearchSysCache1(), SetConfigOption(), SetDatabaseEncoding(), SysCacheGetAttr(), SysCacheGetAttrNotNull(), TextDatumGetCString, TopMemoryContext, and WARNING.

Referenced by InitPostgres().

◆ ClientCheckTimeoutHandler()

static void ClientCheckTimeoutHandler ( void  )
static

Definition at line 1398 of file postinit.c.

1399 {
1401  InterruptPending = true;
1402  SetLatch(MyLatch);
1403 }
volatile sig_atomic_t InterruptPending
Definition: globals.c:31
struct Latch * MyLatch
Definition: globals.c:61
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:596
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:503
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:384
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:776
#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:52
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 1374 of file postinit.c.

1375 {
1377  InterruptPending = true;
1378  SetLatch(MyLatch);
1379 }
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 1382 of file postinit.c.

1383 {
1385  InterruptPending = true;
1386  SetLatch(MyLatch);
1387 }
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 1390 of file postinit.c.

1391 {
1393  InterruptPending = true;
1394  SetLatch(MyLatch);
1395 }
volatile sig_atomic_t IdleStatsUpdateTimeoutPending
Definition: globals.c:41

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

Referenced by InitPostgres().

◆ InitializeMaxBackends()

void InitializeMaxBackends ( void  )

Definition at line 575 of file postinit.c.

576 {
577  Assert(MaxBackends == 0);
578 
579  /* the extra unit accounts for the autovacuum launcher */
582 
584  ereport(ERROR,
585  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
586  errmsg("too many server processes configured"),
587  errdetail("\"max_connections\" (%d) plus \"autovacuum_max_workers\" (%d) plus \"max_worker_processes\" (%d) plus \"max_wal_senders\" (%d) must be less than %d.",
590  MAX_BACKENDS)));
591 }
int autovacuum_max_workers
Definition: autovacuum.c:118
int MaxConnections
Definition: globals.c:141
int MaxBackends
Definition: globals.c:144
int max_worker_processes
Definition: globals.c:142
#define MAX_BACKENDS
Definition: postmaster.h:103
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, and MaxConnections.

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

697 {
698  bool bootstrap = IsBootstrapProcessingMode();
699  bool am_superuser;
700  char *fullpath;
701  char dbname[NAMEDATALEN];
702  int nfree = 0;
703 
704  elog(DEBUG3, "InitPostgres");
705 
706  /*
707  * Add my PGPROC struct to the ProcArray.
708  *
709  * Once I have done this, I am visible to other backends!
710  */
712 
713  /*
714  * Initialize my entry in the shared-invalidation manager's array of
715  * per-backend data.
716  */
717  SharedInvalBackendInit(false);
718 
719  ProcSignalInit();
720 
721  /*
722  * Also set up timeout handlers needed for backend operation. We need
723  * these in every case except bootstrap.
724  */
725  if (!bootstrap)
726  {
737  }
738 
739  /*
740  * If this is either a bootstrap process or a standalone backend, start up
741  * the XLOG machinery, and register to have it closed down at exit. In
742  * other cases, the startup process is responsible for starting up the
743  * XLOG machinery, and the checkpointer for closing it down.
744  */
745  if (!IsUnderPostmaster)
746  {
747  /*
748  * We don't yet have an aux-process resource owner, but StartupXLOG
749  * and ShutdownXLOG will need one. Hence, create said resource owner
750  * (and register a callback to clean it up after ShutdownXLOG runs).
751  */
753 
754  StartupXLOG();
755  /* Release (and warn about) any buffer pins leaked in StartupXLOG */
757  /* Reset CurrentResourceOwner to nothing for the moment */
758  CurrentResourceOwner = NULL;
759 
760  /*
761  * Use before_shmem_exit() so that ShutdownXLOG() can rely on DSM
762  * segments etc to work (which in turn is required for pgstats).
763  */
766  }
767 
768  /*
769  * Initialize the relation cache and the system catalog caches. Note that
770  * no catalog access happens here; we only set up the hashtable structure.
771  * We must do this before starting a transaction because transaction abort
772  * would try to touch these hashtables.
773  */
776  InitPlanCache();
777 
778  /* Initialize portal manager */
780 
781  /* Initialize status reporting */
782  pgstat_beinit();
783 
784  /*
785  * Load relcache entries for the shared system catalogs. This must create
786  * at least entries for pg_database and catalogs used for authentication.
787  */
789 
790  /*
791  * Set up process-exit callback to do pre-shutdown cleanup. This is the
792  * one of the first before_shmem_exit callbacks we register; thus, this
793  * will be one the last things we do before low-level modules like the
794  * buffer manager begin to close down. We need to have this in place
795  * before we begin our first transaction --- if we fail during the
796  * initialization transaction, as is entirely possible, we need the
797  * AbortTransaction call to clean up.
798  */
800 
801  /* The autovacuum launcher is done here */
803  {
804  /* report this backend in the PgBackendStatus array */
805  pgstat_bestart();
806 
807  return;
808  }
809 
810  /*
811  * Start a new transaction here before first access to db, and get a
812  * snapshot. We don't have a use for the snapshot itself, but we're
813  * interested in the secondary effect that it sets RecentGlobalXmin. (This
814  * is critical for anything that reads heap pages, because HOT may decide
815  * to prune them even if the process doesn't attempt to modify any
816  * tuples.)
817  *
818  * FIXME: This comment is inaccurate / the code buggy. A snapshot that is
819  * not pushed/active does not reliably prevent HOT pruning (->xmin could
820  * e.g. be cleared when cache invalidations are processed).
821  */
822  if (!bootstrap)
823  {
824  /* statement_timestamp must be set for timeouts to work correctly */
827 
828  /*
829  * transaction_isolation will have been set to the default by the
830  * above. If the default is "serializable", and we are in hot
831  * standby, we will fail if we don't change it to something lower.
832  * Fortunately, "read committed" is plenty good enough.
833  */
835 
836  (void) GetTransactionSnapshot();
837  }
838 
839  /*
840  * Perform client authentication if necessary, then figure out our
841  * postgres user ID, and see if we are a superuser.
842  *
843  * In standalone mode, autovacuum worker processes and slot sync worker
844  * process, we use a fixed ID, otherwise we figure it out from the
845  * authenticated user name.
846  */
848  {
850  am_superuser = true;
851  }
852  else if (!IsUnderPostmaster)
853  {
855  am_superuser = true;
856  if (!ThereIsAtLeastOneRole())
858  (errcode(ERRCODE_UNDEFINED_OBJECT),
859  errmsg("no roles are defined in this database system"),
860  errhint("You should immediately run CREATE USER \"%s\" SUPERUSER;.",
861  username != NULL ? username : "postgres")));
862  }
863  else if (AmBackgroundWorkerProcess())
864  {
865  if (username == NULL && !OidIsValid(useroid))
866  {
868  am_superuser = true;
869  }
870  else
871  {
873  (flags & INIT_PG_OVERRIDE_ROLE_LOGIN) != 0);
874  am_superuser = superuser();
875  }
876  }
877  else
878  {
879  /* normal multiuser case */
880  Assert(MyProcPort != NULL);
882  InitializeSessionUserId(username, useroid, false);
883  /* ensure that auth_method is actually valid, aka authn_id is not NULL */
887  am_superuser = superuser();
888  }
889 
890  /*
891  * Binary upgrades only allowed super-user connections
892  */
893  if (IsBinaryUpgrade && !am_superuser)
894  {
895  ereport(FATAL,
896  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
897  errmsg("must be superuser to connect in binary upgrade mode")));
898  }
899 
900  /*
901  * The last few connection slots are reserved for superusers and roles
902  * with privileges of pg_use_reserved_connections. Replication
903  * connections are drawn from slots reserved with max_wal_senders and are
904  * not limited by max_connections, superuser_reserved_connections, or
905  * reserved_connections.
906  *
907  * Note: At this point, the new backend has already claimed a proc struct,
908  * so we must check whether the number of free slots is strictly less than
909  * the reserved connection limits.
910  */
911  if (!am_superuser && !am_walsender &&
914  {
915  if (nfree < SuperuserReservedConnections)
916  ereport(FATAL,
917  (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
918  errmsg("remaining connection slots are reserved for roles with the %s attribute",
919  "SUPERUSER")));
920 
921  if (!has_privs_of_role(GetUserId(), ROLE_PG_USE_RESERVED_CONNECTIONS))
922  ereport(FATAL,
923  (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
924  errmsg("remaining connection slots are reserved for roles with privileges of the \"%s\" role",
925  "pg_use_reserved_connections")));
926  }
927 
928  /* Check replication permissions needed for walsender processes. */
929  if (am_walsender)
930  {
931  Assert(!bootstrap);
932 
934  ereport(FATAL,
935  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
936  errmsg("permission denied to start WAL sender"),
937  errdetail("Only roles with the %s attribute may start a WAL sender process.",
938  "REPLICATION")));
939  }
940 
941  /*
942  * If this is a plain walsender only supporting physical replication, we
943  * don't want to connect to any particular database. Just finish the
944  * backend startup by processing any options from the startup packet, and
945  * we're done.
946  */
948  {
949  /* process any options passed in the startup packet */
950  if (MyProcPort != NULL)
951  process_startup_options(MyProcPort, am_superuser);
952 
953  /* Apply PostAuthDelay as soon as we've read all options */
954  if (PostAuthDelay > 0)
955  pg_usleep(PostAuthDelay * 1000000L);
956 
957  /* initialize client encoding */
959 
960  /* report this backend in the PgBackendStatus array */
961  pgstat_bestart();
962 
963  /* close the transaction we started above */
965 
966  return;
967  }
968 
969  /*
970  * Set up the global variables holding database id and default tablespace.
971  * But note we won't actually try to touch the database just yet.
972  *
973  * We take a shortcut in the bootstrap case, otherwise we have to look up
974  * the db's entry in pg_database.
975  */
976  if (bootstrap)
977  {
978  dboid = Template1DbOid;
979  MyDatabaseTableSpace = DEFAULTTABLESPACE_OID;
980  }
981  else if (in_dbname != NULL)
982  {
983  HeapTuple tuple;
984  Form_pg_database dbform;
985 
986  tuple = GetDatabaseTuple(in_dbname);
987  if (!HeapTupleIsValid(tuple))
988  ereport(FATAL,
989  (errcode(ERRCODE_UNDEFINED_DATABASE),
990  errmsg("database \"%s\" does not exist", in_dbname)));
991  dbform = (Form_pg_database) GETSTRUCT(tuple);
992  dboid = dbform->oid;
993  }
994  else if (!OidIsValid(dboid))
995  {
996  /*
997  * If this is a background worker not bound to any particular
998  * database, we're done now. Everything that follows only makes sense
999  * if we are bound to a specific database. We do need to close the
1000  * transaction we started before returning.
1001  */
1002  if (!bootstrap)
1003  {
1004  pgstat_bestart();
1006  }
1007  return;
1008  }
1009 
1010  /*
1011  * Now, take a writer's lock on the database we are trying to connect to.
1012  * If there is a concurrently running DROP DATABASE on that database, this
1013  * will block us until it finishes (and has committed its update of
1014  * pg_database).
1015  *
1016  * Note that the lock is not held long, only until the end of this startup
1017  * transaction. This is OK since we will advertise our use of the
1018  * database in the ProcArray before dropping the lock (in fact, that's the
1019  * next thing to do). Anyone trying a DROP DATABASE after this point will
1020  * see us in the array once they have the lock. Ordering is important for
1021  * this because we don't want to advertise ourselves as being in this
1022  * database until we have the lock; otherwise we create what amounts to a
1023  * deadlock with CountOtherDBBackends().
1024  *
1025  * Note: use of RowExclusiveLock here is reasonable because we envision
1026  * our session as being a concurrent writer of the database. If we had a
1027  * way of declaring a session as being guaranteed-read-only, we could use
1028  * AccessShareLock for such sessions and thereby not conflict against
1029  * CREATE DATABASE.
1030  */
1031  if (!bootstrap)
1032  LockSharedObject(DatabaseRelationId, dboid, 0, RowExclusiveLock);
1033 
1034  /*
1035  * Recheck pg_database to make sure the target database hasn't gone away.
1036  * If there was a concurrent DROP DATABASE, this ensures we will die
1037  * cleanly without creating a mess.
1038  */
1039  if (!bootstrap)
1040  {
1041  HeapTuple tuple;
1042  Form_pg_database datform;
1043 
1044  tuple = GetDatabaseTupleByOid(dboid);
1045  if (HeapTupleIsValid(tuple))
1046  datform = (Form_pg_database) GETSTRUCT(tuple);
1047 
1048  if (!HeapTupleIsValid(tuple) ||
1049  (in_dbname && namestrcmp(&datform->datname, in_dbname)))
1050  {
1051  if (in_dbname)
1052  ereport(FATAL,
1053  (errcode(ERRCODE_UNDEFINED_DATABASE),
1054  errmsg("database \"%s\" does not exist", in_dbname),
1055  errdetail("It seems to have just been dropped or renamed.")));
1056  else
1057  ereport(FATAL,
1058  (errcode(ERRCODE_UNDEFINED_DATABASE),
1059  errmsg("database %u does not exist", dboid)));
1060  }
1061 
1062  strlcpy(dbname, NameStr(datform->datname), sizeof(dbname));
1063 
1064  if (database_is_invalid_form(datform))
1065  {
1066  ereport(FATAL,
1067  errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1068  errmsg("cannot connect to invalid database \"%s\"", dbname),
1069  errhint("Use DROP DATABASE to drop invalid databases."));
1070  }
1071 
1072  MyDatabaseTableSpace = datform->dattablespace;
1073  MyDatabaseHasLoginEventTriggers = datform->dathasloginevt;
1074  /* pass the database name back to the caller */
1075  if (out_dbname)
1076  strcpy(out_dbname, dbname);
1077  }
1078 
1079  /*
1080  * Now that we rechecked, we are certain to be connected to a database and
1081  * thus can set MyDatabaseId.
1082  *
1083  * It is important that MyDatabaseId only be set once we are sure that the
1084  * target database can no longer be concurrently dropped or renamed. For
1085  * example, without this guarantee, pgstat_update_dbstats() could create
1086  * entries for databases that were just dropped in the pgstat shutdown
1087  * callback, which could confuse other code paths like the autovacuum
1088  * scheduler.
1089  */
1090  MyDatabaseId = dboid;
1091 
1092  /*
1093  * Now we can mark our PGPROC entry with the database ID.
1094  *
1095  * We assume this is an atomic store so no lock is needed; though actually
1096  * things would work fine even if it weren't atomic. Anyone searching the
1097  * ProcArray for this database's ID should hold the database lock, so they
1098  * would not be executing concurrently with this store. A process looking
1099  * for another database's ID could in theory see a chance match if it read
1100  * a partially-updated databaseId value; but as long as all such searches
1101  * wait and retry, as in CountOtherDBBackends(), they will certainly see
1102  * the correct value on their next try.
1103  */
1105 
1106  /*
1107  * We established a catalog snapshot while reading pg_authid and/or
1108  * pg_database; but until we have set up MyDatabaseId, we won't react to
1109  * incoming sinval messages for unshared catalogs, so we won't realize it
1110  * if the snapshot has been invalidated. Assume it's no good anymore.
1111  */
1113 
1114  /*
1115  * Now we should be able to access the database directory safely. Verify
1116  * it's there and looks reasonable.
1117  */
1119 
1120  if (!bootstrap)
1121  {
1122  if (access(fullpath, F_OK) == -1)
1123  {
1124  if (errno == ENOENT)
1125  ereport(FATAL,
1126  (errcode(ERRCODE_UNDEFINED_DATABASE),
1127  errmsg("database \"%s\" does not exist",
1128  dbname),
1129  errdetail("The database subdirectory \"%s\" is missing.",
1130  fullpath)));
1131  else
1132  ereport(FATAL,
1134  errmsg("could not access directory \"%s\": %m",
1135  fullpath)));
1136  }
1137 
1138  ValidatePgVersion(fullpath);
1139  }
1140 
1141  SetDatabasePath(fullpath);
1142  pfree(fullpath);
1143 
1144  /*
1145  * It's now possible to do real access to the system catalogs.
1146  *
1147  * Load relcache entries for the system catalogs. This must create at
1148  * least the minimum set of "nailed-in" cache entries.
1149  */
1151 
1152  /* set up ACL framework (so CheckMyDatabase can check permissions) */
1153  initialize_acl();
1154 
1155  /*
1156  * Re-read the pg_database row for our database, check permissions and set
1157  * up database-specific GUC settings. We can't do this until all the
1158  * database-access infrastructure is up. (Also, it wants to know if the
1159  * user is a superuser, so the above stuff has to happen first.)
1160  */
1161  if (!bootstrap)
1162  CheckMyDatabase(dbname, am_superuser,
1163  (flags & INIT_PG_OVERRIDE_ALLOW_CONNS) != 0);
1164 
1165  /*
1166  * Now process any command-line switches and any additional GUC variable
1167  * settings passed in the startup packet. We couldn't do this before
1168  * because we didn't know if client is a superuser.
1169  */
1170  if (MyProcPort != NULL)
1171  process_startup_options(MyProcPort, am_superuser);
1172 
1173  /* Process pg_db_role_setting options */
1175 
1176  /* Apply PostAuthDelay as soon as we've read all options */
1177  if (PostAuthDelay > 0)
1178  pg_usleep(PostAuthDelay * 1000000L);
1179 
1180  /*
1181  * Initialize various default states that can't be set up until we've
1182  * selected the active user and gotten the right GUC settings.
1183  */
1184 
1185  /* set default namespace search path */
1187 
1188  /* initialize client encoding */
1190 
1191  /* Initialize this backend's session state. */
1193 
1194  /*
1195  * If this is an interactive session, load any libraries that should be
1196  * preloaded at backend start. Since those are determined by GUCs, this
1197  * can't happen until GUC settings are complete, but we want it to happen
1198  * during the initial transaction in case anything that requires database
1199  * access needs to be done.
1200  */
1201  if ((flags & INIT_PG_LOAD_SESSION_LIBS) != 0)
1203 
1204  /* report this backend in the PgBackendStatus array */
1205  if (!bootstrap)
1206  pgstat_bestart();
1207 
1208  /* close the transaction we started above */
1209  if (!bootstrap)
1211 }
void initialize_acl(void)
Definition: acl.c:4890
bool has_privs_of_role(Oid member, Oid role)
Definition: acl.c:5134
void pgstat_beinit(void)
void pgstat_bestart(void)
#define OidIsValid(objectId)
Definition: c.h:775
bool database_is_invalid_form(Form_pg_database datform)
Definition: dbcommands.c:3190
int errcode_for_file_access(void)
Definition: elog.c:876
#define DEBUG3
Definition: elog.h:28
bool MyDatabaseHasLoginEventTriggers
Definition: globals.c:96
bool IsBinaryUpgrade
Definition: globals.c:119
Oid MyDatabaseTableSpace
Definition: globals.c:94
struct Port * MyProcPort
Definition: globals.c:50
const char * hba_authname(UserAuth auth_method)
Definition: hba.c:3061
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:1073
#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:454
#define INIT_PG_LOAD_SESSION_LIBS
Definition: miscadmin.h:476
#define AmBackgroundWorkerProcess()
Definition: miscadmin.h:376
#define AmLogicalSlotSyncWorkerProcess()
Definition: miscadmin.h:378
#define AmAutoVacuumLauncherProcess()
Definition: miscadmin.h:374
#define INIT_PG_OVERRIDE_ROLE_LOGIN
Definition: miscadmin.h:478
#define INIT_PG_OVERRIDE_ALLOW_CONNS
Definition: miscadmin.h:477
void InitializeSessionUserId(const char *rolename, Oid roleid, bool bypass_login_check)
Definition: miscinit.c:733
void InitializeSystemUser(const char *authn_id, const char *auth_method)
Definition: miscinit.c:867
void InitializeSessionUserIdStandalone(void)
Definition: miscinit.c:837
void process_session_preload_libraries(void)
Definition: miscinit.c:1857
Oid GetSessionUserId(void)
Definition: miscinit.c:548
void SetDatabasePath(const char *path)
Definition: miscinit.c:328
ClientConnectionInfo MyClientConnectionInfo
Definition: miscinit.c:1010
bool has_rolreplication(Oid roleid)
Definition: miscinit.c:711
void ValidatePgVersion(const char *path)
Definition: miscinit.c:1710
int namestrcmp(Name name, const char *str)
Definition: name.c:247
void InitializeSearchPath(void)
Definition: namespace.c:4721
#define NAMEDATALEN
void pgstat_before_server_shutdown(int code, Datum arg)
Definition: pgstat.c:505
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:101
static void ShutdownPostgres(int code, Datum arg)
Definition: postinit.c:1317
static void IdleInTransactionSessionTimeoutHandler(void)
Definition: postinit.c:1374
static void LockTimeoutHandler(void)
Definition: postinit.c:1356
static void IdleStatsUpdateTimeoutHandler(void)
Definition: postinit.c:1390
static void process_settings(Oid databaseid, Oid roleid)
Definition: postinit.c:1283
static void IdleSessionTimeoutHandler(void)
Definition: postinit.c:1382
static void process_startup_options(Port *port, bool am_superuser)
Definition: postinit.c:1218
static void StatementTimeoutHandler(void)
Definition: postinit.c:1334
static void CheckMyDatabase(const char *name, bool am_superuser, bool override_allow_connections)
Definition: postinit.c:313
static bool ThereIsAtLeastOneRole(void)
Definition: postinit.c:1409
static void PerformAuthentication(Port *port)
Definition: postinit.c:190
static void ClientCheckTimeoutHandler(void)
Definition: postinit.c:1398
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:1366
int ReservedConnections
Definition: postmaster.c:217
int SuperuserReservedConnections
Definition: postmaster.c:216
short access
Definition: preproc-type.c:36
void ProcSignalInit(void)
Definition: procsignal.c:158
void RelationCacheInitializePhase3(void)
Definition: relcache.c:4097
void RelationCacheInitialize(void)
Definition: relcache.c:3992
void RelationCacheInitializePhase2(void)
Definition: relcache.c:4038
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:272
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:216
void InvalidateCatalogSnapshot(void)
Definition: snapmgr.c:422
bool HaveNFreeProcs(int n, int *nfree)
Definition: proc.c:687
void CheckDeadLockAlert(void)
Definition: proc.c:1840
void InitProcessPhase2(void)
Definition: proc.c:488
const char * authn_id
Definition: libpq-be.h:103
UserAuth auth_method
Definition: libpq-be.h:109
Oid databaseId
Definition: proc.h:202
bool superuser(void)
Definition: superuser.c:46
void InitCatalogCache(void)
Definition: syscache.c:107
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:3033
int XactIsoLevel
Definition: xact.c:77
void SetCurrentStatementStartTimestamp(void)
Definition: xact.c:912
void CommitTransactionCommand(void)
Definition: xact.c:3131
#define XACT_READ_COMMITTED
Definition: xact.h:37
void StartupXLOG(void)
Definition: xlog.c:5387
void ShutdownXLOG(int code, Datum arg)
Definition: xlog.c:6539

References am_db_walsender, am_walsender, AmAutoVacuumLauncherProcess, AmAutoVacuumWorkerProcess, AmBackgroundWorkerProcess, AmLogicalSlotSyncWorkerProcess, 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, GetTransactionSnapshot(), 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(), 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 1356 of file postinit.c.

1357 {
1358 #ifdef HAVE_SETSID
1359  /* try to signal whole process group */
1360  kill(-MyProcPid, SIGINT);
1361 #endif
1362  kill(MyProcPid, SIGINT);
1363 }
int MyProcPid
Definition: globals.c:46
#define kill(pid, sig)
Definition: win32_port.h:490

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  */
219  ereport(FATAL,
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:533
bool load_ident(void)
Definition: hba.c:2959
bool load_hba(void)
Definition: hba.c:2583
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:116
bool Log_connections
Definition: postmaster.c:231
bool ClientAuthInProgress
Definition: postmaster.c:350
int AuthenticationTimeout
Definition: postmaster.c:228
static void set_ps_display(const char *activity)
Definition: ps_status.h:40
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:97
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
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 517 of file postinit.c.

518 {
519  StringInfoData s;
520 
521  initStringInfo(&s);
522 
523  while (*optstr)
524  {
525  bool last_was_escape = false;
526 
527  resetStringInfo(&s);
528 
529  /* skip over leading space */
530  while (isspace((unsigned char) *optstr))
531  optstr++;
532 
533  if (*optstr == '\0')
534  break;
535 
536  /*
537  * Parse a single option, stopping at the first space, unless it's
538  * escaped.
539  */
540  while (*optstr)
541  {
542  if (isspace((unsigned char) *optstr) && !last_was_escape)
543  break;
544 
545  if (!last_was_escape && *optstr == '\\')
546  last_was_escape = true;
547  else
548  {
549  last_was_escape = false;
550  appendStringInfoChar(&s, *optstr);
551  }
552 
553  optstr++;
554  }
555 
556  /* now store the option in the next argv[] position */
557  argv[(*argcp)++] = pstrdup(s.data);
558  }
559 
560  pfree(s.data);
561 }
char * pstrdup(const char *in)
Definition: mcxt.c:1696
void resetStringInfo(StringInfo str)
Definition: stringinfo.c:78
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:194

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

1284 {
1285  Relation relsetting;
1286  Snapshot snapshot;
1287 
1288  if (!IsUnderPostmaster)
1289  return;
1290 
1291  relsetting = table_open(DbRoleSettingRelationId, AccessShareLock);
1292 
1293  /* read all the settings under the same snapshot for efficiency */
1294  snapshot = RegisterSnapshot(GetCatalogSnapshot(DbRoleSettingRelationId));
1295 
1296  /* Later settings are ignored if set earlier. */
1297  ApplySetting(snapshot, databaseid, roleid, relsetting, PGC_S_DATABASE_USER);
1298  ApplySetting(snapshot, InvalidOid, roleid, relsetting, PGC_S_USER);
1299  ApplySetting(snapshot, databaseid, InvalidOid, relsetting, PGC_S_DATABASE);
1300  ApplySetting(snapshot, InvalidOid, InvalidOid, relsetting, PGC_S_GLOBAL);
1301 
1302  UnregisterSnapshot(snapshot);
1303  table_close(relsetting, AccessShareLock);
1304 }
@ 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:352
void UnregisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:836
Snapshot RegisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:794

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

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

1318 {
1319  /* Make sure we've killed any active transaction */
1321 
1322  /*
1323  * User locks are not released by transaction end, so be sure to release
1324  * them explicitly.
1325  */
1327 }
void LockReleaseAll(LOCKMETHODID lockmethodid, bool allLocks)
Definition: lock.c:2169
#define USER_LOCKMETHOD
Definition: lock.h:126
void AbortOutOfAnyTransaction(void)
Definition: xact.c:4849

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

Referenced by InitPostgres().

◆ StatementTimeoutHandler()

static void StatementTimeoutHandler ( void  )
static

Definition at line 1334 of file postinit.c.

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

1410 {
1411  Relation pg_authid_rel;
1412  TableScanDesc scan;
1413  bool result;
1414 
1415  pg_authid_rel = table_open(AuthIdRelationId, AccessShareLock);
1416 
1417  scan = table_beginscan_catalog(pg_authid_rel, 0, NULL);
1418  result = (heap_getnext(scan, ForwardScanDirection) != NULL);
1419 
1420  table_endscan(scan);
1421  table_close(pg_authid_rel, AccessShareLock);
1422 
1423  return result;
1424 }
HeapTuple heap_getnext(TableScanDesc sscan, ScanDirection direction)
Definition: heapam.c:1252
@ 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:1019

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

1367 {
1369  InterruptPending = true;
1370  SetLatch(MyLatch);
1371 }
volatile sig_atomic_t TransactionTimeoutPending
Definition: globals.c:37

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

Referenced by InitPostgres().