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/sysattr.h"
#include "access/tableam.h"
#include "access/xact.h"
#include "access/xlog.h"
#include "access/xloginsert.h"
#include "catalog/catalog.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/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)
 
bool check_max_connections (int *newval, void **extra, GucSource source)
 
bool check_autovacuum_max_workers (int *newval, void **extra, GucSource source)
 
bool check_max_worker_processes (int *newval, void **extra, GucSource source)
 
bool check_max_wal_senders (int *newval, void **extra, GucSource source)
 
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 630 of file postinit.c.

631 {
632  Assert(MyProc != NULL);
633 
634  /*
635  * Initialize our input/output/debugging file descriptors.
636  */
637  DebugFileOpen();
638 
639  /*
640  * Initialize file access. Done early so other subsystems can access
641  * files.
642  */
643  InitFileAccess();
644 
645  /*
646  * Initialize statistics reporting. This needs to happen early to ensure
647  * that pgstat's shutdown callback runs after the shutdown callbacks of
648  * all subsystems that can produce stats (like e.g. transaction commits
649  * can).
650  */
652 
653  /* Do local initialization of storage and buffer managers */
654  InitSync();
655  smgrinit();
657 
658  /*
659  * Initialize temporary file access after pgstat, so that the temporary
660  * file shutdown hook can report temporary file statistics.
661  */
663 
664  /*
665  * Initialize local buffers for WAL record construction, in case we ever
666  * try to insert XLOG.
667  */
668  InitXLogInsert();
669 
670  /*
671  * Initialize replication slots after pgstat. The exit hook might need to
672  * drop ephemeral slots, which in turn triggers stats reporting.
673  */
675 }
void InitBufferPoolAccess(void)
Definition: bufmgr.c:3230
void DebugFileOpen(void)
Definition: elog.c:2072
void InitFileAccess(void)
Definition: fd.c:903
void InitTemporaryFileAccess(void)
Definition: fd.c:933
Assert(fmt[strlen(fmt) - 1] !='\n')
void pgstat_initialize(void)
Definition: pgstat.c:540
void ReplicationSlotInitialize(void)
Definition: slot.c:171
void smgrinit(void)
Definition: smgr.c:153
PGPROC * MyProc
Definition: proc.c:67
void InitSync(void)
Definition: sync.c:129
void InitXLogInsert(void)
Definition: xloginsert.c:1349

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

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

◆ check_autovacuum_max_workers()

bool check_autovacuum_max_workers ( int *  newval,
void **  extra,
GucSource  source 
)

Definition at line 589 of file postinit.c.

590 {
591  if (MaxConnections + *newval + 1 +
593  return false;
594  return true;
595 }
int MaxConnections
Definition: globals.c:140
int max_worker_processes
Definition: globals.c:141
#define newval
#define MAX_BACKENDS
Definition: postmaster.h:78
int max_wal_senders
Definition: walsender.c:124

References MAX_BACKENDS, max_wal_senders, max_worker_processes, MaxConnections, and newval.

◆ check_max_connections()

bool check_max_connections ( int *  newval,
void **  extra,
GucSource  source 
)

Definition at line 577 of file postinit.c.

578 {
579  if (*newval + autovacuum_max_workers + 1 +
581  return false;
582  return true;
583 }
int autovacuum_max_workers
Definition: autovacuum.c:118

References autovacuum_max_workers, MAX_BACKENDS, max_wal_senders, max_worker_processes, and newval.

◆ check_max_wal_senders()

bool check_max_wal_senders ( int *  newval,
void **  extra,
GucSource  source 
)

Definition at line 613 of file postinit.c.

614 {
617  return false;
618  return true;
619 }

References autovacuum_max_workers, MAX_BACKENDS, max_worker_processes, MaxConnections, and newval.

◆ check_max_worker_processes()

bool check_max_worker_processes ( int *  newval,
void **  extra,
GucSource  source 
)

Definition at line 601 of file postinit.c.

602 {
605  return false;
606  return true;
607 }

References autovacuum_max_workers, MAX_BACKENDS, max_wal_senders, MaxConnections, and newval.

◆ CheckMyDatabase()

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

Definition at line 314 of file postinit.c.

315 {
316  HeapTuple tup;
317  Form_pg_database dbform;
318  Datum datum;
319  bool isnull;
320  char *collate;
321  char *ctype;
322  char *iculocale;
323 
324  /* Fetch our pg_database row normally, via syscache */
325  tup = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(MyDatabaseId));
326  if (!HeapTupleIsValid(tup))
327  elog(ERROR, "cache lookup failed for database %u", MyDatabaseId);
328  dbform = (Form_pg_database) GETSTRUCT(tup);
329 
330  /* This recheck is strictly paranoia */
331  if (strcmp(name, NameStr(dbform->datname)) != 0)
332  ereport(FATAL,
333  (errcode(ERRCODE_UNDEFINED_DATABASE),
334  errmsg("database \"%s\" has disappeared from pg_database",
335  name),
336  errdetail("Database OID %u now seems to belong to \"%s\".",
337  MyDatabaseId, NameStr(dbform->datname))));
338 
339  /*
340  * Check permissions to connect to the database.
341  *
342  * These checks are not enforced when in standalone mode, so that there is
343  * a way to recover from disabling all access to all databases, for
344  * example "UPDATE pg_database SET datallowconn = false;".
345  *
346  * We do not enforce them for autovacuum worker processes either.
347  */
349  {
350  /*
351  * Check that the database is currently allowing connections.
352  */
353  if (!dbform->datallowconn && !override_allow_connections)
354  ereport(FATAL,
355  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
356  errmsg("database \"%s\" is not currently accepting connections",
357  name)));
358 
359  /*
360  * Check privilege to connect to the database. (The am_superuser test
361  * is redundant, but since we have the flag, might as well check it
362  * and save a few cycles.)
363  */
364  if (!am_superuser &&
365  object_aclcheck(DatabaseRelationId, MyDatabaseId, GetUserId(),
367  ereport(FATAL,
368  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
369  errmsg("permission denied for database \"%s\"", name),
370  errdetail("User does not have CONNECT privilege.")));
371 
372  /*
373  * Check connection limit for this database.
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 &&
383  !am_superuser &&
384  CountDBConnections(MyDatabaseId) > dbform->datconnlimit)
385  ereport(FATAL,
386  (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
387  errmsg("too many connections for database \"%s\"",
388  name)));
389  }
390 
391  /*
392  * OK, we're golden. Next to-do item is to save the encoding info out of
393  * the pg_database tuple.
394  */
395  SetDatabaseEncoding(dbform->encoding);
396  /* Record it as a GUC internal option, too */
397  SetConfigOption("server_encoding", GetDatabaseEncodingName(),
399  /* If we have no other source of client_encoding, use server encoding */
400  SetConfigOption("client_encoding", GetDatabaseEncodingName(),
402 
403  /* assign locale variables */
404  datum = SysCacheGetAttrNotNull(DATABASEOID, tup, Anum_pg_database_datcollate);
405  collate = TextDatumGetCString(datum);
406  datum = SysCacheGetAttrNotNull(DATABASEOID, tup, Anum_pg_database_datctype);
407  ctype = TextDatumGetCString(datum);
408 
409  if (pg_perm_setlocale(LC_COLLATE, collate) == NULL)
410  ereport(FATAL,
411  (errmsg("database locale is incompatible with operating system"),
412  errdetail("The database was initialized with LC_COLLATE \"%s\", "
413  " which is not recognized by setlocale().", collate),
414  errhint("Recreate the database with another locale or install the missing locale.")));
415 
416  if (pg_perm_setlocale(LC_CTYPE, ctype) == NULL)
417  ereport(FATAL,
418  (errmsg("database locale is incompatible with operating system"),
419  errdetail("The database was initialized with LC_CTYPE \"%s\", "
420  " which is not recognized by setlocale().", ctype),
421  errhint("Recreate the database with another locale or install the missing locale.")));
422 
423  if (strcmp(ctype, "C") == 0 ||
424  strcmp(ctype, "POSIX") == 0)
425  database_ctype_is_c = true;
426 
427  if (dbform->datlocprovider == COLLPROVIDER_ICU)
428  {
429  char *icurules;
430 
431  datum = SysCacheGetAttrNotNull(DATABASEOID, tup, Anum_pg_database_daticulocale);
432  iculocale = TextDatumGetCString(datum);
433 
434  datum = SysCacheGetAttr(DATABASEOID, tup, Anum_pg_database_daticurules, &isnull);
435  if (!isnull)
436  icurules = TextDatumGetCString(datum);
437  else
438  icurules = NULL;
439 
440  make_icu_collator(iculocale, icurules, &default_locale);
441  }
442  else
443  iculocale = NULL;
444 
445  default_locale.provider = dbform->datlocprovider;
446 
447  /*
448  * Default locale is currently always deterministic. Nondeterministic
449  * locales currently don't support pattern matching, which would break a
450  * lot of things if applied globally.
451  */
453 
454  /*
455  * Check collation version. See similar code in
456  * pg_newlocale_from_collation(). Note that here we warn instead of error
457  * in any case, so that we don't prevent connecting.
458  */
459  datum = SysCacheGetAttr(DATABASEOID, tup, Anum_pg_database_datcollversion,
460  &isnull);
461  if (!isnull)
462  {
463  char *actual_versionstr;
464  char *collversionstr;
465 
466  collversionstr = TextDatumGetCString(datum);
467 
468  actual_versionstr = get_collation_actual_version(dbform->datlocprovider, dbform->datlocprovider == COLLPROVIDER_ICU ? iculocale : collate);
469  if (!actual_versionstr)
470  /* should not happen */
471  elog(WARNING,
472  "database \"%s\" has no actual collation version, but a version was recorded",
473  name);
474  else if (strcmp(actual_versionstr, collversionstr) != 0)
476  (errmsg("database \"%s\" has a collation version mismatch",
477  name),
478  errdetail("The database was created using collation version %s, "
479  "but the operating system provides version %s.",
480  collversionstr, actual_versionstr),
481  errhint("Rebuild all objects in this database that use the default collation and run "
482  "ALTER DATABASE %s REFRESH COLLATION VERSION, "
483  "or build PostgreSQL with the right library version.",
485  }
486 
487  ReleaseSysCache(tup);
488 }
@ ACLCHECK_OK
Definition: acl.h:182
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition: aclchk.c:3878
bool IsAutoVacuumWorkerProcess(void)
Definition: autovacuum.c:3367
#define TextDatumGetCString(d)
Definition: builtins.h:98
#define NameStr(name)
Definition: c.h:735
int errdetail(const char *fmt,...)
Definition: elog.c:1208
int errhint(const char *fmt,...)
Definition: elog.c:1322
int errcode(int sqlerrcode)
Definition: elog.c:860
int errmsg(const char *fmt,...)
Definition: elog.c:1075
#define FATAL
Definition: elog.h:41
#define WARNING
Definition: elog.h:36
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
bool IsUnderPostmaster
Definition: globals.c:116
Oid MyDatabaseId
Definition: globals.c:90
void SetConfigOption(const char *name, const char *value, GucContext context, GucSource source)
Definition: guc.c:4256
@ 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
const char * GetDatabaseEncodingName(void)
Definition: mbutils.c:1274
void SetDatabaseEncoding(int encoding)
Definition: mbutils.c:1162
Oid GetUserId(void)
Definition: miscinit.c:511
#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:1412
struct pg_locale_struct default_locale
Definition: pg_locale.c:1409
bool database_ctype_is_c
Definition: pg_locale.c:118
char * get_collation_actual_version(char collprovider, const char *collcollate)
Definition: pg_locale.c:1677
char * pg_perm_setlocale(int category, const char *locale)
Definition: pg_locale.c:213
uintptr_t Datum
Definition: postgres.h:64
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
int CountDBConnections(Oid databaseid)
Definition: procarray.c:3541
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:11975
bool deterministic
Definition: pg_locale.h:76
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:267
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:219
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:480
Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition: syscache.c:511
const char * name

References ACL_CONNECT, ACLCHECK_OK, CountDBConnections(), database_ctype_is_c, default_locale, pg_locale_struct::deterministic, elog(), ereport, errcode(), errdetail(), errhint(), errmsg(), ERROR, FATAL, get_collation_actual_version(), GetDatabaseEncodingName(), GETSTRUCT, GetUserId(), HeapTupleIsValid, IsAutoVacuumWorkerProcess(), IsUnderPostmaster, make_icu_collator(), 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, and WARNING.

Referenced by InitPostgres().

◆ ClientCheckTimeoutHandler()

static void ClientCheckTimeoutHandler ( void  )
static

Definition at line 1433 of file postinit.c.

1434 {
1436  InterruptPending = true;
1437  SetLatch(MyLatch);
1438 }
volatile sig_atomic_t InterruptPending
Definition: globals.c:30
struct Latch * MyLatch
Definition: globals.c:59
volatile sig_atomic_t CheckClientConnectionPending
Definition: globals.c:33
void SetLatch(Latch *latch)
Definition: latch.c:633

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

Referenced by InitPostgres().

◆ GetDatabaseTuple()

static HeapTuple GetDatabaseTuple ( const char *  dbname)
static

Definition at line 102 of file postinit.c.

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

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

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

1410 {
1412  InterruptPending = true;
1413  SetLatch(MyLatch);
1414 }
volatile sig_atomic_t IdleInTransactionSessionTimeoutPending
Definition: globals.c:35

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

Referenced by InitPostgres().

◆ IdleSessionTimeoutHandler()

static void IdleSessionTimeoutHandler ( void  )
static

Definition at line 1417 of file postinit.c.

1418 {
1420  InterruptPending = true;
1421  SetLatch(MyLatch);
1422 }
volatile sig_atomic_t IdleSessionTimeoutPending
Definition: globals.c:37

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

Referenced by InitPostgres().

◆ IdleStatsUpdateTimeoutHandler()

static void IdleStatsUpdateTimeoutHandler ( void  )
static

Definition at line 1425 of file postinit.c.

1426 {
1428  InterruptPending = true;
1429  SetLatch(MyLatch);
1430 }
volatile sig_atomic_t IdleStatsUpdateTimeoutPending
Definition: globals.c:40

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

Referenced by InitPostgres().

◆ InitializeMaxBackends()

void InitializeMaxBackends ( void  )

Definition at line 560 of file postinit.c.

561 {
562  Assert(MaxBackends == 0);
563 
564  /* the extra unit accounts for the autovacuum launcher */
567 
568  /* internal error because the values were all checked previously */
570  elog(ERROR, "too many backends configured");
571 }
int MaxBackends
Definition: globals.c:143

References Assert(), autovacuum_max_workers, elog(), 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 721 of file postinit.c.

725 {
726  bool bootstrap = IsBootstrapProcessingMode();
727  bool am_superuser;
728  char *fullpath;
729  char dbname[NAMEDATALEN];
730  int nfree = 0;
731 
732  elog(DEBUG3, "InitPostgres");
733 
734  /*
735  * Add my PGPROC struct to the ProcArray.
736  *
737  * Once I have done this, I am visible to other backends!
738  */
740 
741  /*
742  * Initialize my entry in the shared-invalidation manager's array of
743  * per-backend data.
744  *
745  * Sets up MyBackendId, a unique backend identifier.
746  */
748 
749  SharedInvalBackendInit(false);
750 
751  if (MyBackendId > MaxBackends || MyBackendId <= 0)
752  elog(FATAL, "bad backend ID: %d", MyBackendId);
753 
754  /* Now that we have a BackendId, we can participate in ProcSignal */
756 
757  /*
758  * Also set up timeout handlers needed for backend operation. We need
759  * these in every case except bootstrap.
760  */
761  if (!bootstrap)
762  {
773  }
774 
775  /*
776  * If this is either a bootstrap process or a standalone backend, start up
777  * the XLOG machinery, and register to have it closed down at exit. In
778  * other cases, the startup process is responsible for starting up the
779  * XLOG machinery, and the checkpointer for closing it down.
780  */
781  if (!IsUnderPostmaster)
782  {
783  /*
784  * We don't yet have an aux-process resource owner, but StartupXLOG
785  * and ShutdownXLOG will need one. Hence, create said resource owner
786  * (and register a callback to clean it up after ShutdownXLOG runs).
787  */
789 
790  StartupXLOG();
791  /* Release (and warn about) any buffer pins leaked in StartupXLOG */
793  /* Reset CurrentResourceOwner to nothing for the moment */
794  CurrentResourceOwner = NULL;
795 
796  /*
797  * Use before_shmem_exit() so that ShutdownXLOG() can rely on DSM
798  * segments etc to work (which in turn is required for pgstats).
799  */
802  }
803 
804  /*
805  * Initialize the relation cache and the system catalog caches. Note that
806  * no catalog access happens here; we only set up the hashtable structure.
807  * We must do this before starting a transaction because transaction abort
808  * would try to touch these hashtables.
809  */
812  InitPlanCache();
813 
814  /* Initialize portal manager */
816 
817  /* Initialize status reporting */
818  pgstat_beinit();
819 
820  /*
821  * Load relcache entries for the shared system catalogs. This must create
822  * at least entries for pg_database and catalogs used for authentication.
823  */
825 
826  /*
827  * Set up process-exit callback to do pre-shutdown cleanup. This is the
828  * one of the first before_shmem_exit callbacks we register; thus, this
829  * will be one the last things we do before low-level modules like the
830  * buffer manager begin to close down. We need to have this in place
831  * before we begin our first transaction --- if we fail during the
832  * initialization transaction, as is entirely possible, we need the
833  * AbortTransaction call to clean up.
834  */
836 
837  /* The autovacuum launcher is done here */
839  {
840  /* report this backend in the PgBackendStatus array */
841  pgstat_bestart();
842 
843  return;
844  }
845 
846  /*
847  * Start a new transaction here before first access to db, and get a
848  * snapshot. We don't have a use for the snapshot itself, but we're
849  * interested in the secondary effect that it sets RecentGlobalXmin. (This
850  * is critical for anything that reads heap pages, because HOT may decide
851  * to prune them even if the process doesn't attempt to modify any
852  * tuples.)
853  *
854  * FIXME: This comment is inaccurate / the code buggy. A snapshot that is
855  * not pushed/active does not reliably prevent HOT pruning (->xmin could
856  * e.g. be cleared when cache invalidations are processed).
857  */
858  if (!bootstrap)
859  {
860  /* statement_timestamp must be set for timeouts to work correctly */
863 
864  /*
865  * transaction_isolation will have been set to the default by the
866  * above. If the default is "serializable", and we are in hot
867  * standby, we will fail if we don't change it to something lower.
868  * Fortunately, "read committed" is plenty good enough.
869  */
871 
872  (void) GetTransactionSnapshot();
873  }
874 
875  /*
876  * Perform client authentication if necessary, then figure out our
877  * postgres user ID, and see if we are a superuser.
878  *
879  * In standalone mode and in autovacuum worker processes, we use a fixed
880  * ID, otherwise we figure it out from the authenticated user name.
881  */
882  if (bootstrap || IsAutoVacuumWorkerProcess())
883  {
885  am_superuser = true;
886  }
887  else if (!IsUnderPostmaster)
888  {
890  am_superuser = true;
891  if (!ThereIsAtLeastOneRole())
893  (errcode(ERRCODE_UNDEFINED_OBJECT),
894  errmsg("no roles are defined in this database system"),
895  errhint("You should immediately run CREATE USER \"%s\" SUPERUSER;.",
896  username != NULL ? username : "postgres")));
897  }
898  else if (IsBackgroundWorker)
899  {
900  if (username == NULL && !OidIsValid(useroid))
901  {
903  am_superuser = true;
904  }
905  else
906  {
908  (flags & INIT_PG_OVERRIDE_ROLE_LOGIN) != 0);
909  am_superuser = superuser();
910  }
911  }
912  else
913  {
914  /* normal multiuser case */
915  Assert(MyProcPort != NULL);
917  InitializeSessionUserId(username, useroid, false);
918  /* ensure that auth_method is actually valid, aka authn_id is not NULL */
922  am_superuser = superuser();
923  }
924 
925  /*
926  * Binary upgrades only allowed super-user connections
927  */
928  if (IsBinaryUpgrade && !am_superuser)
929  {
930  ereport(FATAL,
931  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
932  errmsg("must be superuser to connect in binary upgrade mode")));
933  }
934 
935  /*
936  * The last few connection slots are reserved for superusers and roles
937  * with privileges of pg_use_reserved_connections. Replication
938  * connections are drawn from slots reserved with max_wal_senders and are
939  * not limited by max_connections, superuser_reserved_connections, or
940  * reserved_connections.
941  *
942  * Note: At this point, the new backend has already claimed a proc struct,
943  * so we must check whether the number of free slots is strictly less than
944  * the reserved connection limits.
945  */
946  if (!am_superuser && !am_walsender &&
949  {
950  if (nfree < SuperuserReservedConnections)
951  ereport(FATAL,
952  (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
953  errmsg("remaining connection slots are reserved for roles with the %s attribute",
954  "SUPERUSER")));
955 
956  if (!has_privs_of_role(GetUserId(), ROLE_PG_USE_RESERVED_CONNECTIONS))
957  ereport(FATAL,
958  (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
959  errmsg("remaining connection slots are reserved for roles with privileges of the \"%s\" role",
960  "pg_use_reserved_connections")));
961  }
962 
963  /* Check replication permissions needed for walsender processes. */
964  if (am_walsender)
965  {
966  Assert(!bootstrap);
967 
969  ereport(FATAL,
970  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
971  errmsg("permission denied to start WAL sender"),
972  errdetail("Only roles with the %s attribute may start a WAL sender process.",
973  "REPLICATION")));
974  }
975 
976  /*
977  * If this is a plain walsender only supporting physical replication, we
978  * don't want to connect to any particular database. Just finish the
979  * backend startup by processing any options from the startup packet, and
980  * we're done.
981  */
983  {
984  /* process any options passed in the startup packet */
985  if (MyProcPort != NULL)
986  process_startup_options(MyProcPort, am_superuser);
987 
988  /* Apply PostAuthDelay as soon as we've read all options */
989  if (PostAuthDelay > 0)
990  pg_usleep(PostAuthDelay * 1000000L);
991 
992  /* initialize client encoding */
994 
995  /* report this backend in the PgBackendStatus array */
996  pgstat_bestart();
997 
998  /* close the transaction we started above */
1000 
1001  return;
1002  }
1003 
1004  /*
1005  * Set up the global variables holding database id and default tablespace.
1006  * But note we won't actually try to touch the database just yet.
1007  *
1008  * We take a shortcut in the bootstrap case, otherwise we have to look up
1009  * the db's entry in pg_database.
1010  */
1011  if (bootstrap)
1012  {
1013  dboid = Template1DbOid;
1014  MyDatabaseTableSpace = DEFAULTTABLESPACE_OID;
1015  }
1016  else if (in_dbname != NULL)
1017  {
1018  HeapTuple tuple;
1019  Form_pg_database dbform;
1020 
1021  tuple = GetDatabaseTuple(in_dbname);
1022  if (!HeapTupleIsValid(tuple))
1023  ereport(FATAL,
1024  (errcode(ERRCODE_UNDEFINED_DATABASE),
1025  errmsg("database \"%s\" does not exist", in_dbname)));
1026  dbform = (Form_pg_database) GETSTRUCT(tuple);
1027  dboid = dbform->oid;
1028  }
1029  else if (!OidIsValid(dboid))
1030  {
1031  /*
1032  * If this is a background worker not bound to any particular
1033  * database, we're done now. Everything that follows only makes sense
1034  * if we are bound to a specific database. We do need to close the
1035  * transaction we started before returning.
1036  */
1037  if (!bootstrap)
1038  {
1039  pgstat_bestart();
1041  }
1042  return;
1043  }
1044 
1045  /*
1046  * Now, take a writer's lock on the database we are trying to connect to.
1047  * If there is a concurrently running DROP DATABASE on that database, this
1048  * will block us until it finishes (and has committed its update of
1049  * pg_database).
1050  *
1051  * Note that the lock is not held long, only until the end of this startup
1052  * transaction. This is OK since we will advertise our use of the
1053  * database in the ProcArray before dropping the lock (in fact, that's the
1054  * next thing to do). Anyone trying a DROP DATABASE after this point will
1055  * see us in the array once they have the lock. Ordering is important for
1056  * this because we don't want to advertise ourselves as being in this
1057  * database until we have the lock; otherwise we create what amounts to a
1058  * deadlock with CountOtherDBBackends().
1059  *
1060  * Note: use of RowExclusiveLock here is reasonable because we envision
1061  * our session as being a concurrent writer of the database. If we had a
1062  * way of declaring a session as being guaranteed-read-only, we could use
1063  * AccessShareLock for such sessions and thereby not conflict against
1064  * CREATE DATABASE.
1065  */
1066  if (!bootstrap)
1067  LockSharedObject(DatabaseRelationId, dboid, 0, RowExclusiveLock);
1068 
1069  /*
1070  * Recheck pg_database to make sure the target database hasn't gone away.
1071  * If there was a concurrent DROP DATABASE, this ensures we will die
1072  * cleanly without creating a mess.
1073  */
1074  if (!bootstrap)
1075  {
1076  HeapTuple tuple;
1077  Form_pg_database datform;
1078 
1079  tuple = GetDatabaseTupleByOid(dboid);
1080  if (HeapTupleIsValid(tuple))
1081  datform = (Form_pg_database) GETSTRUCT(tuple);
1082 
1083  if (!HeapTupleIsValid(tuple) ||
1084  (in_dbname && namestrcmp(&datform->datname, in_dbname)))
1085  {
1086  if (in_dbname)
1087  ereport(FATAL,
1088  (errcode(ERRCODE_UNDEFINED_DATABASE),
1089  errmsg("database \"%s\" does not exist", in_dbname),
1090  errdetail("It seems to have just been dropped or renamed.")));
1091  else
1092  ereport(FATAL,
1093  (errcode(ERRCODE_UNDEFINED_DATABASE),
1094  errmsg("database %u does not exist", dboid)));
1095  }
1096 
1097  strlcpy(dbname, NameStr(datform->datname), sizeof(dbname));
1098 
1099  if (database_is_invalid_form(datform))
1100  {
1101  ereport(FATAL,
1102  errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1103  errmsg("cannot connect to invalid database \"%s\"", dbname),
1104  errhint("Use DROP DATABASE to drop invalid databases."));
1105  }
1106 
1107  MyDatabaseTableSpace = datform->dattablespace;
1108  MyDatabaseHasLoginEventTriggers = datform->dathasloginevt;
1109  /* pass the database name back to the caller */
1110  if (out_dbname)
1111  strcpy(out_dbname, dbname);
1112  }
1113 
1114  /*
1115  * Now that we rechecked, we are certain to be connected to a database and
1116  * thus can set MyDatabaseId.
1117  *
1118  * It is important that MyDatabaseId only be set once we are sure that the
1119  * target database can no longer be concurrently dropped or renamed. For
1120  * example, without this guarantee, pgstat_update_dbstats() could create
1121  * entries for databases that were just dropped in the pgstat shutdown
1122  * callback, which could confuse other code paths like the autovacuum
1123  * scheduler.
1124  */
1125  MyDatabaseId = dboid;
1126 
1127  /*
1128  * Now we can mark our PGPROC entry with the database ID.
1129  *
1130  * We assume this is an atomic store so no lock is needed; though actually
1131  * things would work fine even if it weren't atomic. Anyone searching the
1132  * ProcArray for this database's ID should hold the database lock, so they
1133  * would not be executing concurrently with this store. A process looking
1134  * for another database's ID could in theory see a chance match if it read
1135  * a partially-updated databaseId value; but as long as all such searches
1136  * wait and retry, as in CountOtherDBBackends(), they will certainly see
1137  * the correct value on their next try.
1138  */
1140 
1141  /*
1142  * We established a catalog snapshot while reading pg_authid and/or
1143  * pg_database; but until we have set up MyDatabaseId, we won't react to
1144  * incoming sinval messages for unshared catalogs, so we won't realize it
1145  * if the snapshot has been invalidated. Assume it's no good anymore.
1146  */
1148 
1149  /*
1150  * Now we should be able to access the database directory safely. Verify
1151  * it's there and looks reasonable.
1152  */
1154 
1155  if (!bootstrap)
1156  {
1157  if (access(fullpath, F_OK) == -1)
1158  {
1159  if (errno == ENOENT)
1160  ereport(FATAL,
1161  (errcode(ERRCODE_UNDEFINED_DATABASE),
1162  errmsg("database \"%s\" does not exist",
1163  dbname),
1164  errdetail("The database subdirectory \"%s\" is missing.",
1165  fullpath)));
1166  else
1167  ereport(FATAL,
1169  errmsg("could not access directory \"%s\": %m",
1170  fullpath)));
1171  }
1172 
1173  ValidatePgVersion(fullpath);
1174  }
1175 
1176  SetDatabasePath(fullpath);
1177  pfree(fullpath);
1178 
1179  /*
1180  * It's now possible to do real access to the system catalogs.
1181  *
1182  * Load relcache entries for the system catalogs. This must create at
1183  * least the minimum set of "nailed-in" cache entries.
1184  */
1186 
1187  /* set up ACL framework (so CheckMyDatabase can check permissions) */
1188  initialize_acl();
1189 
1190  /*
1191  * Re-read the pg_database row for our database, check permissions and set
1192  * up database-specific GUC settings. We can't do this until all the
1193  * database-access infrastructure is up. (Also, it wants to know if the
1194  * user is a superuser, so the above stuff has to happen first.)
1195  */
1196  if (!bootstrap)
1197  CheckMyDatabase(dbname, am_superuser,
1198  (flags & INIT_PG_OVERRIDE_ALLOW_CONNS) != 0);
1199 
1200  /*
1201  * Now process any command-line switches and any additional GUC variable
1202  * settings passed in the startup packet. We couldn't do this before
1203  * because we didn't know if client is a superuser.
1204  */
1205  if (MyProcPort != NULL)
1206  process_startup_options(MyProcPort, am_superuser);
1207 
1208  /* Process pg_db_role_setting options */
1210 
1211  /* Apply PostAuthDelay as soon as we've read all options */
1212  if (PostAuthDelay > 0)
1213  pg_usleep(PostAuthDelay * 1000000L);
1214 
1215  /*
1216  * Initialize various default states that can't be set up until we've
1217  * selected the active user and gotten the right GUC settings.
1218  */
1219 
1220  /* set default namespace search path */
1222 
1223  /* initialize client encoding */
1225 
1226  /* Initialize this backend's session state. */
1228 
1229  /*
1230  * If this is an interactive session, load any libraries that should be
1231  * preloaded at backend start. Since those are determined by GUCs, this
1232  * can't happen until GUC settings are complete, but we want it to happen
1233  * during the initial transaction in case anything that requires database
1234  * access needs to be done.
1235  */
1236  if ((flags & INIT_PG_LOAD_SESSION_LIBS) != 0)
1238 
1239  /* report this backend in the PgBackendStatus array */
1240  if (!bootstrap)
1241  pgstat_bestart();
1242 
1243  /* close the transaction we started above */
1244  if (!bootstrap)
1246 }
void initialize_acl(void)
Definition: acl.c:4870
bool has_privs_of_role(Oid member, Oid role)
Definition: acl.c:5060
bool IsAutoVacuumLauncherProcess(void)
Definition: autovacuum.c:3361
void pgstat_beinit(void)
void pgstat_bestart(void)
#define InvalidBackendId
Definition: backendid.h:23
#define OidIsValid(objectId)
Definition: c.h:764
bool database_is_invalid_form(Form_pg_database datform)
Definition: dbcommands.c:3113
int errcode_for_file_access(void)
Definition: elog.c:883
#define DEBUG3
Definition: elog.h:28
bool MyDatabaseHasLoginEventTriggers
Definition: globals.c:94
bool IsBinaryUpgrade
Definition: globals.c:117
bool IsBackgroundWorker
Definition: globals.c:118
BackendId MyBackendId
Definition: globals.c:86
Oid MyDatabaseTableSpace
Definition: globals.c:92
struct Port * MyProcPort
Definition: globals.c:48
const char * hba_authname(UserAuth auth_method)
Definition: hba.c:3066
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:1046
#define RowExclusiveLock
Definition: lockdefs.h:38
void InitializeClientEncoding(void)
Definition: mbutils.c:282
void pfree(void *pointer)
Definition: mcxt.c:1431
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:415
#define INIT_PG_LOAD_SESSION_LIBS
Definition: miscadmin.h:470
#define INIT_PG_OVERRIDE_ROLE_LOGIN
Definition: miscadmin.h:472
#define INIT_PG_OVERRIDE_ALLOW_CONNS
Definition: miscadmin.h:471
void InitializeSessionUserId(const char *rolename, Oid roleid, bool bypass_login_check)
Definition: miscinit.c:730
void InitializeSystemUser(const char *authn_id, const char *auth_method)
Definition: miscinit.c:863
void InitializeSessionUserIdStandalone(void)
Definition: miscinit.c:834
void process_session_preload_libraries(void)
Definition: miscinit.c:1853
Oid GetSessionUserId(void)
Definition: miscinit.c:545
void SetDatabasePath(const char *path)
Definition: miscinit.c:325
ClientConnectionInfo MyClientConnectionInfo
Definition: miscinit.c:1006
bool has_rolreplication(Oid roleid)
Definition: miscinit.c:708
void ValidatePgVersion(const char *path)
Definition: miscinit.c:1706
int namestrcmp(Name name, const char *str)
Definition: name.c:247
void InitializeSearchPath(void)
Definition: namespace.c:4718
#define NAMEDATALEN
const char * username
Definition: pgbench.c:296
void pgstat_before_server_shutdown(int code, Datum arg)
Definition: pgstat.c:465
void InitPlanCache(void)
Definition: plancache.c:156
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
void EnablePortalManager(void)
Definition: portalmem.c:105
int PostAuthDelay
Definition: postgres.c:100
static void ShutdownPostgres(int code, Datum arg)
Definition: postinit.c:1352
static void IdleInTransactionSessionTimeoutHandler(void)
Definition: postinit.c:1409
static void LockTimeoutHandler(void)
Definition: postinit.c:1391
static void IdleStatsUpdateTimeoutHandler(void)
Definition: postinit.c:1425
static void process_settings(Oid databaseid, Oid roleid)
Definition: postinit.c:1318
static void IdleSessionTimeoutHandler(void)
Definition: postinit.c:1417
static void process_startup_options(Port *port, bool am_superuser)
Definition: postinit.c:1253
static void StatementTimeoutHandler(void)
Definition: postinit.c:1369
static void CheckMyDatabase(const char *name, bool am_superuser, bool override_allow_connections)
Definition: postinit.c:314
static bool ThereIsAtLeastOneRole(void)
Definition: postinit.c:1444
static void PerformAuthentication(Port *port)
Definition: postinit.c:191
static void ClientCheckTimeoutHandler(void)
Definition: postinit.c:1433
static HeapTuple GetDatabaseTuple(const char *dbname)
Definition: postinit.c:102
static HeapTuple GetDatabaseTupleByOid(Oid dboid)
Definition: postinit.c:145
static void TransactionTimeoutHandler(void)
Definition: postinit.c:1401
int ReservedConnections
Definition: postmaster.c:225
int SuperuserReservedConnections
Definition: postmaster.c:224
short access
Definition: preproc-type.c:36
void ProcSignalInit(int pss_idx)
Definition: procsignal.c:162
void RelationCacheInitializePhase3(void)
Definition: relcache.c:4055
void RelationCacheInitialize(void)
Definition: relcache.c:3950
void RelationCacheInitializePhase2(void)
Definition: relcache.c:3996
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:266
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:223
void InvalidateCatalogSnapshot(void)
Definition: snapmgr.c:429
bool HaveNFreeProcs(int n, int *nfree)
Definition: proc.c:683
void CheckDeadLockAlert(void)
Definition: proc.c:1807
void InitProcessPhase2(void)
Definition: proc.c:485
const char * authn_id
Definition: libpq-be.h:114
UserAuth auth_method
Definition: libpq-be.h:120
Oid databaseId
Definition: proc.h:198
bool superuser(void)
Definition: superuser.c:46
void InitCatalogCache(void)
Definition: syscache.c:108
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:118
bool am_db_walsender
Definition: walsender.c:121
void StartTransactionCommand(void)
Definition: xact.c:2953
int XactIsoLevel
Definition: xact.c:79
void SetCurrentStatementStartTimestamp(void)
Definition: xact.c:899
void CommitTransactionCommand(void)
Definition: xact.c:3050
#define XACT_READ_COMMITTED
Definition: xact.h:37
void StartupXLOG(void)
Definition: xlog.c:5319
void ShutdownXLOG(int code, Datum arg)
Definition: xlog.c:6462

References am_db_walsender, am_walsender, 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(), InvalidBackendId, IsAutoVacuumLauncherProcess(), IsAutoVacuumWorkerProcess(), IsBackgroundWorker, IsBinaryUpgrade, IsBootstrapProcessingMode, IsUnderPostmaster, LOCK_TIMEOUT, LockSharedObject(), LockTimeoutHandler(), MaxBackends, MyBackendId, 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 AutoVacLauncherMain(), AutoVacWorkerMain(), BackgroundWorkerInitializeConnection(), BackgroundWorkerInitializeConnectionByOid(), BootstrapModeMain(), and PostgresMain().

◆ LockTimeoutHandler()

static void LockTimeoutHandler ( void  )
static

Definition at line 1391 of file postinit.c.

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

References kill, and MyProcPid.

Referenced by InitPostgres().

◆ PerformAuthentication()

static void PerformAuthentication ( Port port)
static

Definition at line 191 of file postinit.c.

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

503 {
504  StringInfoData s;
505 
506  initStringInfo(&s);
507 
508  while (*optstr)
509  {
510  bool last_was_escape = false;
511 
512  resetStringInfo(&s);
513 
514  /* skip over leading space */
515  while (isspace((unsigned char) *optstr))
516  optstr++;
517 
518  if (*optstr == '\0')
519  break;
520 
521  /*
522  * Parse a single option, stopping at the first space, unless it's
523  * escaped.
524  */
525  while (*optstr)
526  {
527  if (isspace((unsigned char) *optstr) && !last_was_escape)
528  break;
529 
530  if (!last_was_escape && *optstr == '\\')
531  last_was_escape = true;
532  else
533  {
534  last_was_escape = false;
535  appendStringInfoChar(&s, *optstr);
536  }
537 
538  optstr++;
539  }
540 
541  /* now store the option in the next argv[] position */
542  argv[(*argcp)++] = pstrdup(s.data);
543  }
544 
545  pfree(s.data);
546 }
char * pstrdup(const char *in)
Definition: mcxt.c:1619
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 1318 of file postinit.c.

1319 {
1320  Relation relsetting;
1321  Snapshot snapshot;
1322 
1323  if (!IsUnderPostmaster)
1324  return;
1325 
1326  relsetting = table_open(DbRoleSettingRelationId, AccessShareLock);
1327 
1328  /* read all the settings under the same snapshot for efficiency */
1329  snapshot = RegisterSnapshot(GetCatalogSnapshot(DbRoleSettingRelationId));
1330 
1331  /* Later settings are ignored if set earlier. */
1332  ApplySetting(snapshot, databaseid, roleid, relsetting, PGC_S_DATABASE_USER);
1333  ApplySetting(snapshot, InvalidOid, roleid, relsetting, PGC_S_USER);
1334  ApplySetting(snapshot, databaseid, InvalidOid, relsetting, PGC_S_DATABASE);
1335  ApplySetting(snapshot, InvalidOid, InvalidOid, relsetting, PGC_S_GLOBAL);
1336 
1337  UnregisterSnapshot(snapshot);
1338  table_close(relsetting, AccessShareLock);
1339 }
@ 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:359
void UnregisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:843
Snapshot RegisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:801

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

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

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

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

Referenced by InitPostgres().

◆ StatementTimeoutHandler()

static void StatementTimeoutHandler ( void  )
static

Definition at line 1369 of file postinit.c.

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

References ClientAuthInProgress, kill, MyProcPid, and sig.

Referenced by InitPostgres().

◆ ThereIsAtLeastOneRole()

static bool ThereIsAtLeastOneRole ( void  )
static

Definition at line 1444 of file postinit.c.

1445 {
1446  Relation pg_authid_rel;
1447  TableScanDesc scan;
1448  bool result;
1449 
1450  pg_authid_rel = table_open(AuthIdRelationId, AccessShareLock);
1451 
1452  scan = table_beginscan_catalog(pg_authid_rel, 0, NULL);
1453  result = (heap_getnext(scan, ForwardScanDirection) != NULL);
1454 
1455  table_endscan(scan);
1456  table_close(pg_authid_rel, AccessShareLock);
1457 
1458  return result;
1459 }
HeapTuple heap_getnext(TableScanDesc sscan, ScanDirection direction)
Definition: heapam.c:1086
@ 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:1009

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

1402 {
1404  InterruptPending = true;
1405  SetLatch(MyLatch);
1406 }
volatile sig_atomic_t TransactionTimeoutPending
Definition: globals.c:36

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

Referenced by InitPostgres().