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

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

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

593 {
594  if (MaxConnections + *newval + 1 +
596  return false;
597  return true;
598 }
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 580 of file postinit.c.

581 {
582  if (*newval + autovacuum_max_workers + 1 +
584  return false;
585  return true;
586 }
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 616 of file postinit.c.

617 {
620  return false;
621  return true;
622 }

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

605 {
608  return false;
609  return true;
610 }

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

312 {
313  HeapTuple tup;
314  Form_pg_database dbform;
315  Datum datum;
316  bool isnull;
317  char *collate;
318  char *ctype;
319  char *iculocale;
320 
321  /* Fetch our pg_database row normally, via syscache */
323  if (!HeapTupleIsValid(tup))
324  elog(ERROR, "cache lookup failed for database %u", MyDatabaseId);
325  dbform = (Form_pg_database) GETSTRUCT(tup);
326 
327  /* This recheck is strictly paranoia */
328  if (strcmp(name, NameStr(dbform->datname)) != 0)
329  ereport(FATAL,
330  (errcode(ERRCODE_UNDEFINED_DATABASE),
331  errmsg("database \"%s\" has disappeared from pg_database",
332  name),
333  errdetail("Database OID %u now seems to belong to \"%s\".",
334  MyDatabaseId, NameStr(dbform->datname))));
335 
336  /*
337  * Check permissions to connect to the database.
338  *
339  * These checks are not enforced when in standalone mode, so that there is
340  * a way to recover from disabling all access to all databases, for
341  * example "UPDATE pg_database SET datallowconn = false;".
342  *
343  * We do not enforce them for autovacuum worker processes either.
344  */
346  {
347  /*
348  * Check that the database is currently allowing connections.
349  */
350  if (!dbform->datallowconn && !override_allow_connections)
351  ereport(FATAL,
352  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
353  errmsg("database \"%s\" is not currently accepting connections",
354  name)));
355 
356  /*
357  * Check privilege to connect to the database. (The am_superuser test
358  * is redundant, but since we have the flag, might as well check it
359  * and save a few cycles.)
360  */
361  if (!am_superuser &&
362  object_aclcheck(DatabaseRelationId, MyDatabaseId, GetUserId(),
364  ereport(FATAL,
365  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
366  errmsg("permission denied for database \"%s\"", name),
367  errdetail("User does not have CONNECT privilege.")));
368 
369  /*
370  * Check connection limit for this database.
371  *
372  * There is a race condition here --- we create our PGPROC before
373  * checking for other PGPROCs. If two backends did this at about the
374  * same time, they might both think they were over the limit, while
375  * ideally one should succeed and one fail. Getting that to work
376  * exactly seems more trouble than it is worth, however; instead we
377  * just document that the connection limit is approximate.
378  */
379  if (dbform->datconnlimit >= 0 &&
380  !am_superuser &&
381  CountDBConnections(MyDatabaseId) > dbform->datconnlimit)
382  ereport(FATAL,
383  (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
384  errmsg("too many connections for database \"%s\"",
385  name)));
386  }
387 
388  /*
389  * OK, we're golden. Next to-do item is to save the encoding info out of
390  * the pg_database tuple.
391  */
392  SetDatabaseEncoding(dbform->encoding);
393  /* Record it as a GUC internal option, too */
394  SetConfigOption("server_encoding", GetDatabaseEncodingName(),
396  /* If we have no other source of client_encoding, use server encoding */
397  SetConfigOption("client_encoding", GetDatabaseEncodingName(),
399 
400  /* assign locale variables */
401  datum = SysCacheGetAttrNotNull(DATABASEOID, tup, Anum_pg_database_datcollate);
402  collate = TextDatumGetCString(datum);
403  datum = SysCacheGetAttrNotNull(DATABASEOID, tup, Anum_pg_database_datctype);
404  ctype = TextDatumGetCString(datum);
405 
406  if (pg_perm_setlocale(LC_COLLATE, collate) == NULL)
407  ereport(FATAL,
408  (errmsg("database locale is incompatible with operating system"),
409  errdetail("The database was initialized with LC_COLLATE \"%s\", "
410  " which is not recognized by setlocale().", collate),
411  errhint("Recreate the database with another locale or install the missing locale.")));
412 
413  if (pg_perm_setlocale(LC_CTYPE, ctype) == NULL)
414  ereport(FATAL,
415  (errmsg("database locale is incompatible with operating system"),
416  errdetail("The database was initialized with LC_CTYPE \"%s\", "
417  " which is not recognized by setlocale().", ctype),
418  errhint("Recreate the database with another locale or install the missing locale.")));
419 
420  if (strcmp(ctype, "C") == 0 ||
421  strcmp(ctype, "POSIX") == 0)
422  database_ctype_is_c = true;
423 
424  if (dbform->datlocprovider == COLLPROVIDER_ICU)
425  {
426  char *icurules;
427 
428  datum = SysCacheGetAttrNotNull(DATABASEOID, tup, Anum_pg_database_daticulocale);
429  iculocale = TextDatumGetCString(datum);
430 
431  datum = SysCacheGetAttr(DATABASEOID, tup, Anum_pg_database_daticurules, &isnull);
432  if (!isnull)
433  icurules = TextDatumGetCString(datum);
434  else
435  icurules = NULL;
436 
437  make_icu_collator(iculocale, icurules, &default_locale);
438  }
439  else
440  iculocale = NULL;
441 
442  default_locale.provider = dbform->datlocprovider;
443 
444  /*
445  * Default locale is currently always deterministic. Nondeterministic
446  * locales currently don't support pattern matching, which would break a
447  * lot of things if applied globally.
448  */
450 
451  /*
452  * Check collation version. See similar code in
453  * pg_newlocale_from_collation(). Note that here we warn instead of error
454  * in any case, so that we don't prevent connecting.
455  */
456  datum = SysCacheGetAttr(DATABASEOID, tup, Anum_pg_database_datcollversion,
457  &isnull);
458  if (!isnull)
459  {
460  char *actual_versionstr;
461  char *collversionstr;
462 
463  collversionstr = TextDatumGetCString(datum);
464 
465  actual_versionstr = get_collation_actual_version(dbform->datlocprovider, dbform->datlocprovider == COLLPROVIDER_ICU ? iculocale : collate);
466  if (!actual_versionstr)
467  /* should not happen */
468  elog(WARNING,
469  "database \"%s\" has no actual collation version, but a version was recorded",
470  name);
471  else if (strcmp(actual_versionstr, collversionstr) != 0)
473  (errmsg("database \"%s\" has a collation version mismatch",
474  name),
475  errdetail("The database was created using collation version %s, "
476  "but the operating system provides version %s.",
477  collversionstr, actual_versionstr),
478  errhint("Rebuild all objects in this database that use the default collation and run "
479  "ALTER DATABASE %s REFRESH COLLATION VERSION, "
480  "or build PostgreSQL with the right library version.",
482  }
483 
484  /* Make the locale settings visible as GUC variables, too */
485  SetConfigOption("lc_collate", collate, PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
487 
489 
490  ReleaseSysCache(tup);
491 }
@ ACLCHECK_OK
Definition: acl.h:183
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition: aclchk.c:3775
bool IsAutoVacuumWorkerProcess(void)
Definition: autovacuum.c:3324
#define TextDatumGetCString(d)
Definition: builtins.h:95
#define NameStr(name)
Definition: c.h:730
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
const char * name
Definition: encode.c:571
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:510
#define ACL_CONNECT
Definition: parsenodes.h:94
FormData_pg_database * Form_pg_database
Definition: pg_database.h:90
void make_icu_collator(const char *iculocstr, const char *icurules, struct pg_locale_struct *resultp)
Definition: pg_locale.c:1429
struct pg_locale_struct default_locale
Definition: pg_locale.c:1426
void check_strxfrm_bug(void)
Definition: pg_locale.c:1178
bool database_ctype_is_c
Definition: pg_locale.c:114
char * get_collation_actual_version(char collprovider, const char *collcollate)
Definition: pg_locale.c:1707
char * pg_perm_setlocale(int category, const char *locale)
Definition: pg_locale.c:172
uintptr_t Datum
Definition: postgres.h:64
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
int CountDBConnections(Oid databaseid)
Definition: procarray.c:3618
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:11751
bool deterministic
Definition: pg_locale.h:79
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:866
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:818
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1079
Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition: syscache.c:1110
@ DATABASEOID
Definition: syscache.h:55

References ACL_CONNECT, ACLCHECK_OK, check_strxfrm_bug(), 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 1409 of file postinit.c.

1410 {
1412  InterruptPending = true;
1413  SetLatch(MyLatch);
1414 }
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:607

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:680
#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 1385 of file postinit.c.

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

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

1402 {
1404  InterruptPending = true;
1405  SetLatch(MyLatch);
1406 }
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 563 of file postinit.c.

564 {
565  Assert(MaxBackends == 0);
566 
567  /* the extra unit accounts for the autovacuum launcher */
570 
571  /* internal error because the values were all checked previously */
573  elog(ERROR, "too many backends configured");
574 }
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 722 of file postinit.c.

727 {
728  bool bootstrap = IsBootstrapProcessingMode();
729  bool am_superuser;
730  char *fullpath;
731  char dbname[NAMEDATALEN];
732  int nfree = 0;
733 
734  elog(DEBUG3, "InitPostgres");
735 
736  /*
737  * Add my PGPROC struct to the ProcArray.
738  *
739  * Once I have done this, I am visible to other backends!
740  */
742 
743  /*
744  * Initialize my entry in the shared-invalidation manager's array of
745  * per-backend data.
746  *
747  * Sets up MyBackendId, a unique backend identifier.
748  */
750 
751  SharedInvalBackendInit(false);
752 
753  if (MyBackendId > MaxBackends || MyBackendId <= 0)
754  elog(FATAL, "bad backend ID: %d", MyBackendId);
755 
756  /* Now that we have a BackendId, we can participate in ProcSignal */
758 
759  /*
760  * Also set up timeout handlers needed for backend operation. We need
761  * these in every case except bootstrap.
762  */
763  if (!bootstrap)
764  {
774  }
775 
776  /*
777  * If this is either a bootstrap process or a standalone backend, start up
778  * the XLOG machinery, and register to have it closed down at exit. In
779  * other cases, the startup process is responsible for starting up the
780  * XLOG machinery, and the checkpointer for closing it down.
781  */
782  if (!IsUnderPostmaster)
783  {
784  /*
785  * We don't yet have an aux-process resource owner, but StartupXLOG
786  * and ShutdownXLOG will need one. Hence, create said resource owner
787  * (and register a callback to clean it up after ShutdownXLOG runs).
788  */
790 
791  StartupXLOG();
792  /* Release (and warn about) any buffer pins leaked in StartupXLOG */
794  /* Reset CurrentResourceOwner to nothing for the moment */
795  CurrentResourceOwner = NULL;
796 
797  /*
798  * Use before_shmem_exit() so that ShutdownXLOG() can rely on DSM
799  * segments etc to work (which in turn is required for pgstats).
800  */
803  }
804 
805  /*
806  * Initialize the relation cache and the system catalog caches. Note that
807  * no catalog access happens here; we only set up the hashtable structure.
808  * We must do this before starting a transaction because transaction abort
809  * would try to touch these hashtables.
810  */
813  InitPlanCache();
814 
815  /* Initialize portal manager */
817 
818  /* Initialize status reporting */
819  pgstat_beinit();
820 
821  /*
822  * Load relcache entries for the shared system catalogs. This must create
823  * at least entries for pg_database and catalogs used for authentication.
824  */
826 
827  /*
828  * Set up process-exit callback to do pre-shutdown cleanup. This is the
829  * one of the first before_shmem_exit callbacks we register; thus, this
830  * will be one the last things we do before low-level modules like the
831  * buffer manager begin to close down. We need to have this in place
832  * before we begin our first transaction --- if we fail during the
833  * initialization transaction, as is entirely possible, we need the
834  * AbortTransaction call to clean up.
835  */
837 
838  /* The autovacuum launcher is done here */
840  {
841  /* report this backend in the PgBackendStatus array */
842  pgstat_bestart();
843 
844  return;
845  }
846 
847  /*
848  * Start a new transaction here before first access to db, and get a
849  * snapshot. We don't have a use for the snapshot itself, but we're
850  * interested in the secondary effect that it sets RecentGlobalXmin. (This
851  * is critical for anything that reads heap pages, because HOT may decide
852  * to prune them even if the process doesn't attempt to modify any
853  * tuples.)
854  *
855  * FIXME: This comment is inaccurate / the code buggy. A snapshot that is
856  * not pushed/active does not reliably prevent HOT pruning (->xmin could
857  * e.g. be cleared when cache invalidations are processed).
858  */
859  if (!bootstrap)
860  {
861  /* statement_timestamp must be set for timeouts to work correctly */
864 
865  /*
866  * transaction_isolation will have been set to the default by the
867  * above. If the default is "serializable", and we are in hot
868  * standby, we will fail if we don't change it to something lower.
869  * Fortunately, "read committed" is plenty good enough.
870  */
872 
873  (void) GetTransactionSnapshot();
874  }
875 
876  /*
877  * Perform client authentication if necessary, then figure out our
878  * postgres user ID, and see if we are a superuser.
879  *
880  * In standalone mode and in autovacuum worker processes, we use a fixed
881  * ID, otherwise we figure it out from the authenticated user name.
882  */
883  if (bootstrap || IsAutoVacuumWorkerProcess())
884  {
886  am_superuser = true;
887  }
888  else if (!IsUnderPostmaster)
889  {
891  am_superuser = true;
892  if (!ThereIsAtLeastOneRole())
894  (errcode(ERRCODE_UNDEFINED_OBJECT),
895  errmsg("no roles are defined in this database system"),
896  errhint("You should immediately run CREATE USER \"%s\" SUPERUSER;.",
897  username != NULL ? username : "postgres")));
898  }
899  else if (IsBackgroundWorker)
900  {
901  if (username == NULL && !OidIsValid(useroid))
902  {
904  am_superuser = true;
905  }
906  else
907  {
909  am_superuser = superuser();
910  }
911  }
912  else
913  {
914  /* normal multiuser case */
915  Assert(MyProcPort != NULL);
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 with
937  * privileges of pg_use_reserved_connections. Replication connections are
938  * drawn from slots reserved with max_wal_senders and are not limited by
939  * 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 %s",
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  MyDatabaseId = 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  MyDatabaseId = dbform->oid;
1028  MyDatabaseTableSpace = dbform->dattablespace;
1029  /* take database name from the caller, just for paranoia */
1030  strlcpy(dbname, in_dbname, sizeof(dbname));
1031  }
1032  else if (OidIsValid(dboid))
1033  {
1034  /* caller specified database by OID */
1035  HeapTuple tuple;
1036  Form_pg_database dbform;
1037 
1038  tuple = GetDatabaseTupleByOid(dboid);
1039  if (!HeapTupleIsValid(tuple))
1040  ereport(FATAL,
1041  (errcode(ERRCODE_UNDEFINED_DATABASE),
1042  errmsg("database %u does not exist", dboid)));
1043  dbform = (Form_pg_database) GETSTRUCT(tuple);
1044  MyDatabaseId = dbform->oid;
1045  MyDatabaseTableSpace = dbform->dattablespace;
1046  Assert(MyDatabaseId == dboid);
1047  strlcpy(dbname, NameStr(dbform->datname), sizeof(dbname));
1048  /* pass the database name back to the caller */
1049  if (out_dbname)
1050  strcpy(out_dbname, dbname);
1051  }
1052  else
1053  {
1054  /*
1055  * If this is a background worker not bound to any particular
1056  * database, we're done now. Everything that follows only makes sense
1057  * if we are bound to a specific database. We do need to close the
1058  * transaction we started before returning.
1059  */
1060  if (!bootstrap)
1061  {
1062  pgstat_bestart();
1064  }
1065  return;
1066  }
1067 
1068  /*
1069  * Now, take a writer's lock on the database we are trying to connect to.
1070  * If there is a concurrently running DROP DATABASE on that database, this
1071  * will block us until it finishes (and has committed its update of
1072  * pg_database).
1073  *
1074  * Note that the lock is not held long, only until the end of this startup
1075  * transaction. This is OK since we will advertise our use of the
1076  * database in the ProcArray before dropping the lock (in fact, that's the
1077  * next thing to do). Anyone trying a DROP DATABASE after this point will
1078  * see us in the array once they have the lock. Ordering is important for
1079  * this because we don't want to advertise ourselves as being in this
1080  * database until we have the lock; otherwise we create what amounts to a
1081  * deadlock with CountOtherDBBackends().
1082  *
1083  * Note: use of RowExclusiveLock here is reasonable because we envision
1084  * our session as being a concurrent writer of the database. If we had a
1085  * way of declaring a session as being guaranteed-read-only, we could use
1086  * AccessShareLock for such sessions and thereby not conflict against
1087  * CREATE DATABASE.
1088  */
1089  if (!bootstrap)
1090  LockSharedObject(DatabaseRelationId, MyDatabaseId, 0,
1092 
1093  /*
1094  * Now we can mark our PGPROC entry with the database ID.
1095  *
1096  * We assume this is an atomic store so no lock is needed; though actually
1097  * things would work fine even if it weren't atomic. Anyone searching the
1098  * ProcArray for this database's ID should hold the database lock, so they
1099  * would not be executing concurrently with this store. A process looking
1100  * for another database's ID could in theory see a chance match if it read
1101  * a partially-updated databaseId value; but as long as all such searches
1102  * wait and retry, as in CountOtherDBBackends(), they will certainly see
1103  * the correct value on their next try.
1104  */
1106 
1107  /*
1108  * We established a catalog snapshot while reading pg_authid and/or
1109  * pg_database; but until we have set up MyDatabaseId, we won't react to
1110  * incoming sinval messages for unshared catalogs, so we won't realize it
1111  * if the snapshot has been invalidated. Assume it's no good anymore.
1112  */
1114 
1115  /*
1116  * Recheck pg_database to make sure the target database hasn't gone away.
1117  * If there was a concurrent DROP DATABASE, this ensures we will die
1118  * cleanly without creating a mess.
1119  */
1120  if (!bootstrap)
1121  {
1122  HeapTuple tuple;
1123 
1124  tuple = GetDatabaseTuple(dbname);
1125  if (!HeapTupleIsValid(tuple) ||
1126  MyDatabaseId != ((Form_pg_database) GETSTRUCT(tuple))->oid ||
1127  MyDatabaseTableSpace != ((Form_pg_database) GETSTRUCT(tuple))->dattablespace)
1128  ereport(FATAL,
1129  (errcode(ERRCODE_UNDEFINED_DATABASE),
1130  errmsg("database \"%s\" does not exist", dbname),
1131  errdetail("It seems to have just been dropped or renamed.")));
1132  }
1133 
1134  /*
1135  * Now we should be able to access the database directory safely. Verify
1136  * it's there and looks reasonable.
1137  */
1139 
1140  if (!bootstrap)
1141  {
1142  if (access(fullpath, F_OK) == -1)
1143  {
1144  if (errno == ENOENT)
1145  ereport(FATAL,
1146  (errcode(ERRCODE_UNDEFINED_DATABASE),
1147  errmsg("database \"%s\" does not exist",
1148  dbname),
1149  errdetail("The database subdirectory \"%s\" is missing.",
1150  fullpath)));
1151  else
1152  ereport(FATAL,
1154  errmsg("could not access directory \"%s\": %m",
1155  fullpath)));
1156  }
1157 
1158  ValidatePgVersion(fullpath);
1159  }
1160 
1161  SetDatabasePath(fullpath);
1162  pfree(fullpath);
1163 
1164  /*
1165  * It's now possible to do real access to the system catalogs.
1166  *
1167  * Load relcache entries for the system catalogs. This must create at
1168  * least the minimum set of "nailed-in" cache entries.
1169  */
1171 
1172  /* set up ACL framework (so CheckMyDatabase can check permissions) */
1173  initialize_acl();
1174 
1175  /*
1176  * Re-read the pg_database row for our database, check permissions and set
1177  * up database-specific GUC settings. We can't do this until all the
1178  * database-access infrastructure is up. (Also, it wants to know if the
1179  * user is a superuser, so the above stuff has to happen first.)
1180  */
1181  if (!bootstrap)
1182  CheckMyDatabase(dbname, am_superuser, override_allow_connections);
1183 
1184  /*
1185  * Now process any command-line switches and any additional GUC variable
1186  * settings passed in the startup packet. We couldn't do this before
1187  * because we didn't know if client is a superuser.
1188  */
1189  if (MyProcPort != NULL)
1190  process_startup_options(MyProcPort, am_superuser);
1191 
1192  /* Process pg_db_role_setting options */
1194 
1195  /* Apply PostAuthDelay as soon as we've read all options */
1196  if (PostAuthDelay > 0)
1197  pg_usleep(PostAuthDelay * 1000000L);
1198 
1199  /*
1200  * Initialize various default states that can't be set up until we've
1201  * selected the active user and gotten the right GUC settings.
1202  */
1203 
1204  /* set default namespace search path */
1206 
1207  /* initialize client encoding */
1209 
1210  /* Initialize this backend's session state. */
1212 
1213  /*
1214  * If this is an interactive session, load any libraries that should be
1215  * preloaded at backend start. Since those are determined by GUCs, this
1216  * can't happen until GUC settings are complete, but we want it to happen
1217  * during the initial transaction in case anything that requires database
1218  * access needs to be done.
1219  */
1220  if (load_session_libraries)
1222 
1223  /* report this backend in the PgBackendStatus array */
1224  if (!bootstrap)
1225  pgstat_bestart();
1226 
1227  /* close the transaction we started above */
1228  if (!bootstrap)
1230 }
void initialize_acl(void)
Definition: acl.c:4779
bool has_privs_of_role(Oid member, Oid role)
Definition: acl.c:4969
bool IsAutoVacuumLauncherProcess(void)
Definition: autovacuum.c:3318
void pgstat_beinit(void)
void pgstat_bestart(void)
#define InvalidBackendId
Definition: backendid.h:23
#define OidIsValid(objectId)
Definition: c.h:759
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:3162
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:1436
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:405
void InitializeSystemUser(const char *authn_id, const char *auth_method)
Definition: miscinit.c:855
void InitializeSessionUserIdStandalone(void)
Definition: miscinit.c:832
void process_session_preload_libraries(void)
Definition: miscinit.c:1861
Oid GetSessionUserId(void)
Definition: miscinit.c:544
void SetDatabasePath(const char *path)
Definition: miscinit.c:323
void InitializeSessionUserId(const char *rolename, Oid roleid)
Definition: miscinit.c:729
ClientConnectionInfo MyClientConnectionInfo
Definition: miscinit.c:1014
bool has_rolreplication(Oid roleid)
Definition: miscinit.c:707
void ValidatePgVersion(const char *path)
Definition: miscinit.c:1714
void InitializeSearchPath(void)
Definition: namespace.c:4369
#define NAMEDATALEN
const char * username
Definition: pgbench.c:306
void pgstat_before_server_shutdown(int code, Datum arg)
Definition: pgstat.c:458
void InitPlanCache(void)
Definition: plancache.c:127
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:95
static void ShutdownPostgres(int code, Datum arg)
Definition: postinit.c:1336
static void IdleInTransactionSessionTimeoutHandler(void)
Definition: postinit.c:1385
static void LockTimeoutHandler(void)
Definition: postinit.c:1375
static void IdleStatsUpdateTimeoutHandler(void)
Definition: postinit.c:1401
static void process_settings(Oid databaseid, Oid roleid)
Definition: postinit.c:1302
static void IdleSessionTimeoutHandler(void)
Definition: postinit.c:1393
static void process_startup_options(Port *port, bool am_superuser)
Definition: postinit.c:1237
static void StatementTimeoutHandler(void)
Definition: postinit.c:1353
static void CheckMyDatabase(const char *name, bool am_superuser, bool override_allow_connections)
Definition: postinit.c:311
static bool ThereIsAtLeastOneRole(void)
Definition: postinit.c:1420
static void PerformAuthentication(Port *port)
Definition: postinit.c:190
static void ClientCheckTimeoutHandler(void)
Definition: postinit.c:1409
static HeapTuple GetDatabaseTuple(const char *dbname)
Definition: postinit.c:101
static HeapTuple GetDatabaseTupleByOid(Oid dboid)
Definition: postinit.c:144
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:4039
void RelationCacheInitialize(void)
Definition: relcache.c:3934
void RelationCacheInitializePhase2(void)
Definition: relcache.c:3980
char * GetDatabasePath(Oid dbOid, Oid spcOid)
Definition: relpath.c:110
void ReleaseAuxProcessResources(bool isCommit)
Definition: resowner.c:912
ResourceOwner CurrentResourceOwner
Definition: resowner.c:146
void CreateAuxProcessResourceOwner(void)
Definition: resowner.c:892
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:251
void InvalidateCatalogSnapshot(void)
Definition: snapmgr.c:457
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:113
UserAuth auth_method
Definition: libpq-be.h:119
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:2938
int XactIsoLevel
Definition: xact.c:79
void SetCurrentStatementStartTimestamp(void)
Definition: xact.c:899
void CommitTransactionCommand(void)
Definition: xact.c:3035
#define XACT_READ_COMMITTED
Definition: xact.h:37
void StartupXLOG(void)
Definition: xlog.c:5020
void ShutdownXLOG(int code, Datum arg)
Definition: xlog.c:6159

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

1376 {
1377 #ifdef HAVE_SETSID
1378  /* try to signal whole process group */
1379  kill(-MyProcPid, SIGINT);
1380 #endif
1381  kill(MyProcPid, SIGINT);
1382 }
int MyProcPid
Definition: globals.c:44
#define kill(pid, sig)
Definition: win32_port.h:489

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, principal=%s)"),
286  be_gssapi_get_auth(port) ? _("yes") : _("no"),
287  be_gssapi_get_enc(port) ? _("yes") : _("no"),
288  princ);
289  else
290  appendStringInfo(&logmsg,
291  _(" GSS (authenticated=%s, encrypted=%s)"),
292  be_gssapi_get_auth(port) ? _("yes") : _("no"),
293  be_gssapi_get_enc(port) ? _("yes") : _("no"));
294  }
295 #endif
296 
297  ereport(LOG, errmsg_internal("%s", logmsg.data));
298  pfree(logmsg.data);
299  }
300 
301  set_ps_display("startup");
302 
303  ClientAuthInProgress = false; /* client_min_messages is active now */
304 }
void ClientAuthentication(Port *port)
Definition: auth.c:383
bool be_gssapi_get_auth(Port *port)
bool be_gssapi_get_enc(Port *port)
const char * be_gssapi_get_princ(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:529
bool load_ident(void)
Definition: hba.c:3043
bool load_hba(void)
Definition: hba.c:2651
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:90
bool Log_connections
Definition: postmaster.c:238
bool ClientAuthInProgress
Definition: postmaster.c:356
int AuthenticationTimeout
Definition: postmaster.c:235
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_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 505 of file postinit.c.

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

1303 {
1304  Relation relsetting;
1305  Snapshot snapshot;
1306 
1307  if (!IsUnderPostmaster)
1308  return;
1309 
1310  relsetting = table_open(DbRoleSettingRelationId, AccessShareLock);
1311 
1312  /* read all the settings under the same snapshot for efficiency */
1313  snapshot = RegisterSnapshot(GetCatalogSnapshot(DbRoleSettingRelationId));
1314 
1315  /* Later settings are ignored if set earlier. */
1316  ApplySetting(snapshot, databaseid, roleid, relsetting, PGC_S_DATABASE_USER);
1317  ApplySetting(snapshot, InvalidOid, roleid, relsetting, PGC_S_USER);
1318  ApplySetting(snapshot, databaseid, InvalidOid, relsetting, PGC_S_DATABASE);
1319  ApplySetting(snapshot, InvalidOid, InvalidOid, relsetting, PGC_S_GLOBAL);
1320 
1321  UnregisterSnapshot(snapshot);
1322  table_close(relsetting, AccessShareLock);
1323 }
@ 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:387
void UnregisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:871
Snapshot RegisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:829

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

1238 {
1239  GucContext gucctx;
1240  ListCell *gucopts;
1241 
1242  gucctx = am_superuser ? PGC_SU_BACKEND : PGC_BACKEND;
1243 
1244  /*
1245  * First process any command-line switches that were included in the
1246  * startup packet, if we are in a regular backend.
1247  */
1248  if (port->cmdline_options != NULL)
1249  {
1250  /*
1251  * The maximum possible number of commandline arguments that could
1252  * come from port->cmdline_options is (strlen + 1) / 2; see
1253  * pg_split_opts().
1254  */
1255  char **av;
1256  int maxac;
1257  int ac;
1258 
1259  maxac = 2 + (strlen(port->cmdline_options) + 1) / 2;
1260 
1261  av = (char **) palloc(maxac * sizeof(char *));
1262  ac = 0;
1263 
1264  av[ac++] = "postgres";
1265 
1266  pg_split_opts(av, &ac, port->cmdline_options);
1267 
1268  av[ac] = NULL;
1269 
1270  Assert(ac < maxac);
1271 
1272  (void) process_postgres_switches(ac, av, gucctx, NULL);
1273  }
1274 
1275  /*
1276  * Process any additional GUC variable settings passed in startup packet.
1277  * These are handled exactly like command-line variables.
1278  */
1279  gucopts = list_head(port->guc_options);
1280  while (gucopts)
1281  {
1282  char *name;
1283  char *value;
1284 
1285  name = lfirst(gucopts);
1286  gucopts = lnext(port->guc_options, gucopts);
1287 
1288  value = lfirst(gucopts);
1289  gucopts = lnext(port->guc_options, gucopts);
1290 
1292  }
1293 }
@ PGC_S_CLIENT
Definition: guc.h:118
GucContext
Definition: guc.h:68
@ PGC_SU_BACKEND
Definition: guc.h:72
static struct @145 value
void * palloc(Size size)
Definition: mcxt.c:1210
#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:3703
void pg_split_opts(char **argv, int *argcp, const char *optstr)
Definition: postinit.c:505
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 1336 of file postinit.c.

1337 {
1338  /* Make sure we've killed any active transaction */
1340 
1341  /*
1342  * User locks are not released by transaction end, so be sure to release
1343  * them explicitly.
1344  */
1346 }
void LockReleaseAll(LOCKMETHODID lockmethodid, bool allLocks)
Definition: lock.c:2154
#define USER_LOCKMETHOD
Definition: lock.h:126
void AbortOutOfAnyTransaction(void)
Definition: xact.c:4713

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

Referenced by InitPostgres().

◆ StatementTimeoutHandler()

static void StatementTimeoutHandler ( void  )
static

Definition at line 1353 of file postinit.c.

1354 {
1355  int sig = SIGINT;
1356 
1357  /*
1358  * During authentication the timeout is used to deal with
1359  * authentication_timeout - we want to quit in response to such timeouts.
1360  */
1362  sig = SIGTERM;
1363 
1364 #ifdef HAVE_SETSID
1365  /* try to signal whole process group */
1366  kill(-MyProcPid, sig);
1367 #endif
1368  kill(MyProcPid, sig);
1369 }
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 1420 of file postinit.c.

1421 {
1422  Relation pg_authid_rel;
1423  TableScanDesc scan;
1424  bool result;
1425 
1426  pg_authid_rel = table_open(AuthIdRelationId, AccessShareLock);
1427 
1428  scan = table_beginscan_catalog(pg_authid_rel, 0, NULL);
1429  result = (heap_getnext(scan, ForwardScanDirection) != NULL);
1430 
1431  table_endscan(scan);
1432  table_close(pg_authid_rel, AccessShareLock);
1433 
1434  return result;
1435 }
HeapTuple heap_getnext(TableScanDesc sscan, ScanDirection direction)
Definition: heapam.c:1093
@ 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:1011

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

Referenced by InitPostgres().