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 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, bool load_session_libraries, bool override_allow_connections, char *out_dbname)
 

Function Documentation

◆ BaseInit()

void BaseInit ( void  )

Definition at line 629 of file postinit.c.

630 {
631  Assert(MyProc != NULL);
632 
633  /*
634  * Initialize our input/output/debugging file descriptors.
635  */
636  DebugFileOpen();
637 
638  /*
639  * Initialize file access. Done early so other subsystems can access
640  * files.
641  */
642  InitFileAccess();
643 
644  /*
645  * Initialize statistics reporting. This needs to happen early to ensure
646  * that pgstat's shutdown callback runs after the shutdown callbacks of
647  * all subsystems that can produce stats (like e.g. transaction commits
648  * can).
649  */
651 
652  /* Do local initialization of storage and buffer managers */
653  InitSync();
654  smgrinit();
656 
657  /*
658  * Initialize temporary file access after pgstat, so that the temporary
659  * file shutdown hook can report temporary file statistics.
660  */
662 
663  /*
664  * Initialize local buffers for WAL record construction, in case we ever
665  * try to insert XLOG.
666  */
667  InitXLogInsert();
668 
669  /*
670  * Initialize replication slots after pgstat. The exit hook might need to
671  * drop ephemeral slots, which in turn triggers stats reporting.
672  */
674 }
void InitBufferPoolAccess(void)
Definition: bufmgr.c:3149
void DebugFileOpen(void)
Definition: elog.c:2066
void InitFileAccess(void)
Definition: fd.c:855
void InitTemporaryFileAccess(void)
Definition: fd.c:885
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:115
PGPROC * MyProc
Definition: proc.c:66
void InitSync(void)
Definition: sync.c:129
void InitXLogInsert(void)
Definition: xloginsert.c:1336

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

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

◆ check_autovacuum_max_workers()

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

Definition at line 588 of file postinit.c.

589 {
590  if (MaxConnections + *newval + 1 +
592  return false;
593  return true;
594 }
int MaxConnections
Definition: globals.c:137
int max_worker_processes
Definition: globals.c:138
#define newval
#define MAX_BACKENDS
Definition: postmaster.h:78
int max_wal_senders
Definition: walsender.c:122

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

577 {
578  if (*newval + autovacuum_max_workers + 1 +
580  return false;
581  return true;
582 }
int autovacuum_max_workers
Definition: autovacuum.c:117

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

613 {
616  return false;
617  return true;
618 }

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

601 {
604  return false;
605  return true;
606 }

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 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 *iculocale;
322 
323  /* Fetch our pg_database row normally, via syscache */
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_ICU)
427  {
428  char *icurules;
429 
430  datum = SysCacheGetAttrNotNull(DATABASEOID, tup, Anum_pg_database_daticulocale);
431  iculocale = TextDatumGetCString(datum);
432 
433  datum = SysCacheGetAttr(DATABASEOID, tup, Anum_pg_database_daticurules, &isnull);
434  if (!isnull)
435  icurules = TextDatumGetCString(datum);
436  else
437  icurules = NULL;
438 
439  make_icu_collator(iculocale, icurules, &default_locale);
440  }
441  else
442  iculocale = NULL;
443 
444  default_locale.provider = dbform->datlocprovider;
445 
446  /*
447  * Default locale is currently always deterministic. Nondeterministic
448  * locales currently don't support pattern matching, which would break a
449  * lot of things if applied globally.
450  */
452 
453  /*
454  * Check collation version. See similar code in
455  * pg_newlocale_from_collation(). Note that here we warn instead of error
456  * in any case, so that we don't prevent connecting.
457  */
458  datum = SysCacheGetAttr(DATABASEOID, tup, Anum_pg_database_datcollversion,
459  &isnull);
460  if (!isnull)
461  {
462  char *actual_versionstr;
463  char *collversionstr;
464 
465  collversionstr = TextDatumGetCString(datum);
466 
467  actual_versionstr = get_collation_actual_version(dbform->datlocprovider, dbform->datlocprovider == COLLPROVIDER_ICU ? iculocale : collate);
468  if (!actual_versionstr)
469  /* should not happen */
470  elog(WARNING,
471  "database \"%s\" has no actual collation version, but a version was recorded",
472  name);
473  else if (strcmp(actual_versionstr, collversionstr) != 0)
475  (errmsg("database \"%s\" has a collation version mismatch",
476  name),
477  errdetail("The database was created using collation version %s, "
478  "but the operating system provides version %s.",
479  collversionstr, actual_versionstr),
480  errhint("Rebuild all objects in this database that use the default collation and run "
481  "ALTER DATABASE %s REFRESH COLLATION VERSION, "
482  "or build PostgreSQL with the right library version.",
484  }
485 
486  ReleaseSysCache(tup);
487 }
@ ACLCHECK_OK
Definition: acl.h:182
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition: aclchk.c:3760
bool IsAutoVacuumWorkerProcess(void)
Definition: autovacuum.c:3397
#define TextDatumGetCString(d)
Definition: builtins.h:95
#define NameStr(name)
Definition: c.h:735
int errdetail(const char *fmt,...)
Definition: elog.c:1202
int errhint(const char *fmt,...)
Definition: elog.c:1316
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#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:113
Oid MyDatabaseId
Definition: globals.c:89
void SetConfigOption(const char *name, const char *value, GucContext context, GucSource source)
Definition: guc.c:4176
@ 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:509
#define ACL_CONNECT
Definition: parsenodes.h:94
FormData_pg_database * Form_pg_database
Definition: pg_database.h:93
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:3536
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:11965
bool deterministic
Definition: pg_locale.h:76
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:868
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:820
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1081
Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition: syscache.c:1112
@ DATABASEOID
Definition: syscache.h:55
const char * name

References ACL_CONNECT, ACLCHECK_OK, CountDBConnections(), database_ctype_is_c, DATABASEOID, 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 1419 of file postinit.c.

1420 {
1422  InterruptPending = true;
1423  SetLatch(MyLatch);
1424 }
volatile sig_atomic_t InterruptPending
Definition: globals.c:30
struct Latch * MyLatch
Definition: globals.c:58
volatile sig_atomic_t CheckClientConnectionPending
Definition: globals.c:33
void SetLatch(Latch *latch)
Definition: latch.c:605

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: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:768
#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: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 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 1395 of file postinit.c.

1396 {
1398  InterruptPending = true;
1399  SetLatch(MyLatch);
1400 }
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 1403 of file postinit.c.

1404 {
1406  InterruptPending = true;
1407  SetLatch(MyLatch);
1408 }
volatile sig_atomic_t IdleSessionTimeoutPending
Definition: globals.c:36

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

Referenced by InitPostgres().

◆ IdleStatsUpdateTimeoutHandler()

static void IdleStatsUpdateTimeoutHandler ( void  )
static

Definition at line 1411 of file postinit.c.

1412 {
1414  InterruptPending = true;
1415  SetLatch(MyLatch);
1416 }
volatile sig_atomic_t IdleStatsUpdateTimeoutPending
Definition: globals.c:39

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

Referenced by InitPostgres().

◆ InitializeMaxBackends()

void InitializeMaxBackends ( void  )

Definition at line 559 of file postinit.c.

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

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,
bool  load_session_libraries,
bool  override_allow_connections,
char *  out_dbname 
)

Definition at line 718 of file postinit.c.

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

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(), 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, 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(), 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 1385 of file postinit.c.

1386 {
1387 #ifdef HAVE_SETSID
1388  /* try to signal whole process group */
1389  kill(-MyProcPid, SIGINT);
1390 #endif
1391  kill(MyProcPid, SIGINT);
1392 }
int MyProcPid
Definition: globals.c:44
#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 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: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:1156
#define _(x)
Definition: elog.c:91
#define LOG
Definition: elog.h:31
char * HbaFileName
Definition: guc_tables.c:537
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:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:153
static int port
Definition: pg_regress.c:109
bool Log_connections
Definition: postmaster.c:239
bool ClientAuthInProgress
Definition: postmaster.c:356
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:91
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
void enable_timeout_after(TimeoutId id, int delay_ms)
Definition: timeout.c:564
void disable_timeout(TimeoutId id, bool keep_indicator)
Definition: timeout.c:689

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

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

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

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

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

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

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

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

Referenced by InitPostgres().

◆ StatementTimeoutHandler()

static void StatementTimeoutHandler ( void  )
static

Definition at line 1363 of file postinit.c.

1364 {
1365  int sig = SIGINT;
1366 
1367  /*
1368  * During authentication the timeout is used to deal with
1369  * authentication_timeout - we want to quit in response to such timeouts.
1370  */
1372  sig = SIGTERM;
1373 
1374 #ifdef HAVE_SETSID
1375  /* try to signal whole process group */
1376  kill(-MyProcPid, sig);
1377 #endif
1378  kill(MyProcPid, sig);
1379 }
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 1430 of file postinit.c.

1431 {
1432  Relation pg_authid_rel;
1433  TableScanDesc scan;
1434  bool result;
1435 
1436  pg_authid_rel = table_open(AuthIdRelationId, AccessShareLock);
1437 
1438  scan = table_beginscan_catalog(pg_authid_rel, 0, NULL);
1439  result = (heap_getnext(scan, ForwardScanDirection) != NULL);
1440 
1441  table_endscan(scan);
1442  table_close(pg_authid_rel, AccessShareLock);
1443 
1444  return result;
1445 }
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().