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.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)
 
void BaseInit (void)
 
void InitPostgres (const char *in_dbname, Oid dboid, const char *username, Oid useroid, char *out_dbname, bool override_allow_connections)
 

Function Documentation

◆ BaseInit()

void BaseInit ( void  )

Definition at line 573 of file postinit.c.

574 {
575  Assert(MyProc != NULL);
576 
577  /*
578  * Initialize our input/output/debugging file descriptors.
579  */
580  DebugFileOpen();
581 
582  /*
583  * Initialize file access. Done early so other subsystems can access
584  * files.
585  */
586  InitFileAccess();
587 
588  /*
589  * Initialize statistics reporting. This needs to happen early to ensure
590  * that pgstat's shutdown callback runs after the shutdown callbacks of
591  * all subsystems that can produce stats (like e.g. transaction commits
592  * can).
593  */
595 
596  /* Do local initialization of storage and buffer managers */
597  InitSync();
598  smgrinit();
600 
601  /*
602  * Initialize temporary file access after pgstat, so that the temporary
603  * file shutdown hook can report temporary file statistics.
604  */
606 
607  /*
608  * Initialize local buffers for WAL record construction, in case we ever
609  * try to insert XLOG.
610  */
611  InitXLogInsert();
612 
613  /*
614  * Initialize replication slots after pgstat. The exit hook might need to
615  * drop ephemeral slots, which in turn triggers stats reporting.
616  */
618 }
void InitBufferPoolAccess(void)
Definition: bufmgr.c:2604
void DebugFileOpen(void)
Definition: elog.c:1917
void InitFileAccess(void)
Definition: fd.c:883
void InitTemporaryFileAccess(void)
Definition: fd.c:913
Assert(fmt[strlen(fmt) - 1] !='\n')
void pgstat_initialize(void)
Definition: pgstat.c:522
void ReplicationSlotInitialize(void)
Definition: slot.c:169
void smgrinit(void)
Definition: smgr.c:111
PGPROC * MyProc
Definition: proc.c:68
void InitSync(void)
Definition: sync.c:131
void InitXLogInsert(void)
Definition: xloginsert.c:1284

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

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

◆ CheckMyDatabase()

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

Definition at line 310 of file postinit.c.

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

References ACL_CONNECT, ACLCHECK_OK, Assert(), check_strxfrm_bug(), CountDBConnections(), 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, ObjectIdGetDatum, pg_database_aclcheck(), pg_perm_setlocale(), PGC_BACKEND, PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT, PGC_S_OVERRIDE, pg_locale_struct::provider, quote_identifier(), ReleaseSysCache(), SearchSysCache1(), SetConfigOption(), SetDatabaseEncoding(), SysCacheGetAttr(), TextDatumGetCString, and WARNING.

Referenced by InitPostgres().

◆ ClientCheckTimeoutHandler()

static void ClientCheckTimeoutHandler ( void  )
static

Definition at line 1315 of file postinit.c.

1316 {
1318  InterruptPending = true;
1319  SetLatch(MyLatch);
1320 }
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:566

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:598
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:505
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:386
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:680
#define AccessShareLock
Definition: lockdefs.h:36
#define CStringGetDatum(X)
Definition: postgres.h:622
bool criticalSharedRelcachesBuilt
Definition: relcache.c:145
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:167
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

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

1292 {
1294  InterruptPending = true;
1295  SetLatch(MyLatch);
1296 }
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 1299 of file postinit.c.

1300 {
1302  InterruptPending = true;
1303  SetLatch(MyLatch);
1304 }
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 1307 of file postinit.c.

1308 {
1310  InterruptPending = true;
1311  SetLatch(MyLatch);
1312 }
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 551 of file postinit.c.

552 {
553  Assert(MaxBackends == 0);
554 
555  /* the extra unit accounts for the autovacuum launcher */
558 
559  /* internal error because the values were all checked previously */
561  elog(ERROR, "too many backends configured");
562 }
int autovacuum_max_workers
Definition: autovacuum.c:116
int MaxConnections
Definition: globals.c:137
int MaxBackends
Definition: globals.c:140
int max_worker_processes
Definition: globals.c:138
#define MAX_BACKENDS
Definition: postmaster.h:75
int max_wal_senders
Definition: walsender.c:122

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

Definition at line 646 of file postinit.c.

648 {
649  bool bootstrap = IsBootstrapProcessingMode();
650  bool am_superuser;
651  char *fullpath;
652  char dbname[NAMEDATALEN];
653 
654  elog(DEBUG3, "InitPostgres");
655 
656  /*
657  * Add my PGPROC struct to the ProcArray.
658  *
659  * Once I have done this, I am visible to other backends!
660  */
662 
663  /*
664  * Initialize my entry in the shared-invalidation manager's array of
665  * per-backend data.
666  *
667  * Sets up MyBackendId, a unique backend identifier.
668  */
670 
671  SharedInvalBackendInit(false);
672 
673  if (MyBackendId > MaxBackends || MyBackendId <= 0)
674  elog(FATAL, "bad backend ID: %d", MyBackendId);
675 
676  /* Now that we have a BackendId, we can participate in ProcSignal */
678 
679  /*
680  * Also set up timeout handlers needed for backend operation. We need
681  * these in every case except bootstrap.
682  */
683  if (!bootstrap)
684  {
694  }
695 
696  /*
697  * If this is either a bootstrap process or a standalone backend, start up
698  * the XLOG machinery, and register to have it closed down at exit. In
699  * other cases, the startup process is responsible for starting up the
700  * XLOG machinery, and the checkpointer for closing it down.
701  */
702  if (!IsUnderPostmaster)
703  {
704  /*
705  * We don't yet have an aux-process resource owner, but StartupXLOG
706  * and ShutdownXLOG will need one. Hence, create said resource owner
707  * (and register a callback to clean it up after ShutdownXLOG runs).
708  */
710 
711  StartupXLOG();
712  /* Release (and warn about) any buffer pins leaked in StartupXLOG */
714  /* Reset CurrentResourceOwner to nothing for the moment */
715  CurrentResourceOwner = NULL;
716 
717  /*
718  * Use before_shmem_exit() so that ShutdownXLOG() can rely on DSM
719  * segments etc to work (which in turn is required for pgstats).
720  */
723  }
724 
725  /*
726  * Initialize the relation cache and the system catalog caches. Note that
727  * no catalog access happens here; we only set up the hashtable structure.
728  * We must do this before starting a transaction because transaction abort
729  * would try to touch these hashtables.
730  */
733  InitPlanCache();
734 
735  /* Initialize portal manager */
737 
738  /* Initialize status reporting */
739  pgstat_beinit();
740 
741  /*
742  * Load relcache entries for the shared system catalogs. This must create
743  * at least entries for pg_database and catalogs used for authentication.
744  */
746 
747  /*
748  * Set up process-exit callback to do pre-shutdown cleanup. This is the
749  * one of the first before_shmem_exit callbacks we register; thus, this
750  * will be one the last things we do before low-level modules like the
751  * buffer manager begin to close down. We need to have this in place
752  * before we begin our first transaction --- if we fail during the
753  * initialization transaction, as is entirely possible, we need the
754  * AbortTransaction call to clean up.
755  */
757 
758  /* The autovacuum launcher is done here */
760  {
761  /* report this backend in the PgBackendStatus array */
762  pgstat_bestart();
763 
764  return;
765  }
766 
767  /*
768  * Start a new transaction here before first access to db, and get a
769  * snapshot. We don't have a use for the snapshot itself, but we're
770  * interested in the secondary effect that it sets RecentGlobalXmin. (This
771  * is critical for anything that reads heap pages, because HOT may decide
772  * to prune them even if the process doesn't attempt to modify any
773  * tuples.)
774  *
775  * FIXME: This comment is inaccurate / the code buggy. A snapshot that is
776  * not pushed/active does not reliably prevent HOT pruning (->xmin could
777  * e.g. be cleared when cache invalidations are processed).
778  */
779  if (!bootstrap)
780  {
781  /* statement_timestamp must be set for timeouts to work correctly */
784 
785  /*
786  * transaction_isolation will have been set to the default by the
787  * above. If the default is "serializable", and we are in hot
788  * standby, we will fail if we don't change it to something lower.
789  * Fortunately, "read committed" is plenty good enough.
790  */
792 
793  (void) GetTransactionSnapshot();
794  }
795 
796  /*
797  * Perform client authentication if necessary, then figure out our
798  * postgres user ID, and see if we are a superuser.
799  *
800  * In standalone mode and in autovacuum worker processes, we use a fixed
801  * ID, otherwise we figure it out from the authenticated user name.
802  */
803  if (bootstrap || IsAutoVacuumWorkerProcess())
804  {
806  am_superuser = true;
807  }
808  else if (!IsUnderPostmaster)
809  {
811  am_superuser = true;
812  if (!ThereIsAtLeastOneRole())
814  (errcode(ERRCODE_UNDEFINED_OBJECT),
815  errmsg("no roles are defined in this database system"),
816  errhint("You should immediately run CREATE USER \"%s\" SUPERUSER;.",
817  username != NULL ? username : "postgres")));
818  }
819  else if (IsBackgroundWorker)
820  {
821  if (username == NULL && !OidIsValid(useroid))
822  {
824  am_superuser = true;
825  }
826  else
827  {
829  am_superuser = superuser();
830  }
831  }
832  else
833  {
834  /* normal multiuser case */
835  Assert(MyProcPort != NULL);
838  am_superuser = superuser();
839  }
840 
841  /*
842  * Binary upgrades only allowed super-user connections
843  */
844  if (IsBinaryUpgrade && !am_superuser)
845  {
846  ereport(FATAL,
847  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
848  errmsg("must be superuser to connect in binary upgrade mode")));
849  }
850 
851  /*
852  * The last few connection slots are reserved for superusers. Replication
853  * connections are drawn from slots reserved with max_wal_senders and not
854  * limited by max_connections or superuser_reserved_connections.
855  */
856  if (!am_superuser && !am_walsender &&
857  ReservedBackends > 0 &&
859  ereport(FATAL,
860  (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
861  errmsg("remaining connection slots are reserved for non-replication superuser connections")));
862 
863  /* Check replication permissions needed for walsender processes. */
864  if (am_walsender)
865  {
866  Assert(!bootstrap);
867 
868  if (!superuser() && !has_rolreplication(GetUserId()))
869  ereport(FATAL,
870  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
871  errmsg("must be superuser or replication role to start walsender")));
872  }
873 
874  /*
875  * If this is a plain walsender only supporting physical replication, we
876  * don't want to connect to any particular database. Just finish the
877  * backend startup by processing any options from the startup packet, and
878  * we're done.
879  */
881  {
882  /* process any options passed in the startup packet */
883  if (MyProcPort != NULL)
884  process_startup_options(MyProcPort, am_superuser);
885 
886  /* Apply PostAuthDelay as soon as we've read all options */
887  if (PostAuthDelay > 0)
888  pg_usleep(PostAuthDelay * 1000000L);
889 
890  /* initialize client encoding */
892 
893  /* report this backend in the PgBackendStatus array */
894  pgstat_bestart();
895 
896  /* close the transaction we started above */
898 
899  return;
900  }
901 
902  /*
903  * Set up the global variables holding database id and default tablespace.
904  * But note we won't actually try to touch the database just yet.
905  *
906  * We take a shortcut in the bootstrap case, otherwise we have to look up
907  * the db's entry in pg_database.
908  */
909  if (bootstrap)
910  {
911  MyDatabaseId = Template1DbOid;
912  MyDatabaseTableSpace = DEFAULTTABLESPACE_OID;
913  }
914  else if (in_dbname != NULL)
915  {
916  HeapTuple tuple;
917  Form_pg_database dbform;
918 
919  tuple = GetDatabaseTuple(in_dbname);
920  if (!HeapTupleIsValid(tuple))
921  ereport(FATAL,
922  (errcode(ERRCODE_UNDEFINED_DATABASE),
923  errmsg("database \"%s\" does not exist", in_dbname)));
924  dbform = (Form_pg_database) GETSTRUCT(tuple);
925  MyDatabaseId = dbform->oid;
926  MyDatabaseTableSpace = dbform->dattablespace;
927  /* take database name from the caller, just for paranoia */
928  strlcpy(dbname, in_dbname, sizeof(dbname));
929  }
930  else if (OidIsValid(dboid))
931  {
932  /* caller specified database by OID */
933  HeapTuple tuple;
934  Form_pg_database dbform;
935 
936  tuple = GetDatabaseTupleByOid(dboid);
937  if (!HeapTupleIsValid(tuple))
938  ereport(FATAL,
939  (errcode(ERRCODE_UNDEFINED_DATABASE),
940  errmsg("database %u does not exist", dboid)));
941  dbform = (Form_pg_database) GETSTRUCT(tuple);
942  MyDatabaseId = dbform->oid;
943  MyDatabaseTableSpace = dbform->dattablespace;
944  Assert(MyDatabaseId == dboid);
945  strlcpy(dbname, NameStr(dbform->datname), sizeof(dbname));
946  /* pass the database name back to the caller */
947  if (out_dbname)
948  strcpy(out_dbname, dbname);
949  }
950  else
951  {
952  /*
953  * If this is a background worker not bound to any particular
954  * database, we're done now. Everything that follows only makes sense
955  * if we are bound to a specific database. We do need to close the
956  * transaction we started before returning.
957  */
958  if (!bootstrap)
959  {
960  pgstat_bestart();
962  }
963  return;
964  }
965 
966  /*
967  * Now, take a writer's lock on the database we are trying to connect to.
968  * If there is a concurrently running DROP DATABASE on that database, this
969  * will block us until it finishes (and has committed its update of
970  * pg_database).
971  *
972  * Note that the lock is not held long, only until the end of this startup
973  * transaction. This is OK since we will advertise our use of the
974  * database in the ProcArray before dropping the lock (in fact, that's the
975  * next thing to do). Anyone trying a DROP DATABASE after this point will
976  * see us in the array once they have the lock. Ordering is important for
977  * this because we don't want to advertise ourselves as being in this
978  * database until we have the lock; otherwise we create what amounts to a
979  * deadlock with CountOtherDBBackends().
980  *
981  * Note: use of RowExclusiveLock here is reasonable because we envision
982  * our session as being a concurrent writer of the database. If we had a
983  * way of declaring a session as being guaranteed-read-only, we could use
984  * AccessShareLock for such sessions and thereby not conflict against
985  * CREATE DATABASE.
986  */
987  if (!bootstrap)
988  LockSharedObject(DatabaseRelationId, MyDatabaseId, 0,
990 
991  /*
992  * Now we can mark our PGPROC entry with the database ID.
993  *
994  * We assume this is an atomic store so no lock is needed; though actually
995  * things would work fine even if it weren't atomic. Anyone searching the
996  * ProcArray for this database's ID should hold the database lock, so they
997  * would not be executing concurrently with this store. A process looking
998  * for another database's ID could in theory see a chance match if it read
999  * a partially-updated databaseId value; but as long as all such searches
1000  * wait and retry, as in CountOtherDBBackends(), they will certainly see
1001  * the correct value on their next try.
1002  */
1004 
1005  /*
1006  * We established a catalog snapshot while reading pg_authid and/or
1007  * pg_database; but until we have set up MyDatabaseId, we won't react to
1008  * incoming sinval messages for unshared catalogs, so we won't realize it
1009  * if the snapshot has been invalidated. Assume it's no good anymore.
1010  */
1012 
1013  /*
1014  * Recheck pg_database to make sure the target database hasn't gone away.
1015  * If there was a concurrent DROP DATABASE, this ensures we will die
1016  * cleanly without creating a mess.
1017  */
1018  if (!bootstrap)
1019  {
1020  HeapTuple tuple;
1021 
1022  tuple = GetDatabaseTuple(dbname);
1023  if (!HeapTupleIsValid(tuple) ||
1024  MyDatabaseId != ((Form_pg_database) GETSTRUCT(tuple))->oid ||
1025  MyDatabaseTableSpace != ((Form_pg_database) GETSTRUCT(tuple))->dattablespace)
1026  ereport(FATAL,
1027  (errcode(ERRCODE_UNDEFINED_DATABASE),
1028  errmsg("database \"%s\" does not exist", dbname),
1029  errdetail("It seems to have just been dropped or renamed.")));
1030  }
1031 
1032  /*
1033  * Now we should be able to access the database directory safely. Verify
1034  * it's there and looks reasonable.
1035  */
1037 
1038  if (!bootstrap)
1039  {
1040  if (access(fullpath, F_OK) == -1)
1041  {
1042  if (errno == ENOENT)
1043  ereport(FATAL,
1044  (errcode(ERRCODE_UNDEFINED_DATABASE),
1045  errmsg("database \"%s\" does not exist",
1046  dbname),
1047  errdetail("The database subdirectory \"%s\" is missing.",
1048  fullpath)));
1049  else
1050  ereport(FATAL,
1052  errmsg("could not access directory \"%s\": %m",
1053  fullpath)));
1054  }
1055 
1056  ValidatePgVersion(fullpath);
1057  }
1058 
1059  SetDatabasePath(fullpath);
1060  pfree(fullpath);
1061 
1062  /*
1063  * It's now possible to do real access to the system catalogs.
1064  *
1065  * Load relcache entries for the system catalogs. This must create at
1066  * least the minimum set of "nailed-in" cache entries.
1067  */
1069 
1070  /* set up ACL framework (so CheckMyDatabase can check permissions) */
1071  initialize_acl();
1072 
1073  /*
1074  * Re-read the pg_database row for our database, check permissions and set
1075  * up database-specific GUC settings. We can't do this until all the
1076  * database-access infrastructure is up. (Also, it wants to know if the
1077  * user is a superuser, so the above stuff has to happen first.)
1078  */
1079  if (!bootstrap)
1080  CheckMyDatabase(dbname, am_superuser, override_allow_connections);
1081 
1082  /*
1083  * Now process any command-line switches and any additional GUC variable
1084  * settings passed in the startup packet. We couldn't do this before
1085  * because we didn't know if client is a superuser.
1086  */
1087  if (MyProcPort != NULL)
1088  process_startup_options(MyProcPort, am_superuser);
1089 
1090  /* Process pg_db_role_setting options */
1092 
1093  /* Apply PostAuthDelay as soon as we've read all options */
1094  if (PostAuthDelay > 0)
1095  pg_usleep(PostAuthDelay * 1000000L);
1096 
1097  /*
1098  * Initialize various default states that can't be set up until we've
1099  * selected the active user and gotten the right GUC settings.
1100  */
1101 
1102  /* set default namespace search path */
1104 
1105  /* initialize client encoding */
1107 
1108  /* Initialize this backend's session state. */
1110 
1111  /* report this backend in the PgBackendStatus array */
1112  if (!bootstrap)
1113  pgstat_bestart();
1114 
1115  /* close the transaction we started above */
1116  if (!bootstrap)
1118 }
void initialize_acl(void)
Definition: acl.c:4756
bool IsAutoVacuumLauncherProcess(void)
Definition: autovacuum.c:3303
void pgstat_beinit(void)
void pgstat_bestart(void)
#define InvalidBackendId
Definition: backendid.h:23
#define OidIsValid(objectId)
Definition: c.h:710
int errcode_for_file_access(void)
Definition: elog.c:716
#define DEBUG3
Definition: elog.h:22
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
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:281
void pfree(void *pointer)
Definition: mcxt.c:1175
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:406
void InitializeSessionUserIdStandalone(void)
Definition: miscinit.c:800
Oid GetSessionUserId(void)
Definition: miscinit.c:526
void SetDatabasePath(const char *path)
Definition: miscinit.c:305
void InitializeSessionUserId(const char *rolename, Oid roleid)
Definition: miscinit.c:697
bool has_rolreplication(Oid roleid)
Definition: miscinit.c:679
void ValidatePgVersion(const char *path)
Definition: miscinit.c:1550
void InitializeSearchPath(void)
Definition: namespace.c:4372
#define NAMEDATALEN
const char * username
Definition: pgbench.c:309
void pgstat_before_server_shutdown(int code, Datum arg)
Definition: pgstat.c:447
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:103
static void ShutdownPostgres(int code, Datum arg)
Definition: postinit.c:1224
static void IdleInTransactionSessionTimeoutHandler(void)
Definition: postinit.c:1291
static void LockTimeoutHandler(void)
Definition: postinit.c:1281
static void IdleStatsUpdateTimeoutHandler(void)
Definition: postinit.c:1307
static void process_settings(Oid databaseid, Oid roleid)
Definition: postinit.c:1190
static void IdleSessionTimeoutHandler(void)
Definition: postinit.c:1299
static void process_startup_options(Port *port, bool am_superuser)
Definition: postinit.c:1125
static void StatementTimeoutHandler(void)
Definition: postinit.c:1259
static void CheckMyDatabase(const char *name, bool am_superuser, bool override_allow_connections)
Definition: postinit.c:310
static bool ThereIsAtLeastOneRole(void)
Definition: postinit.c:1326
static void PerformAuthentication(Port *port)
Definition: postinit.c:190
static void ClientCheckTimeoutHandler(void)
Definition: postinit.c:1315
static HeapTuple GetDatabaseTuple(const char *dbname)
Definition: postinit.c:101
static HeapTuple GetDatabaseTupleByOid(Oid dboid)
Definition: postinit.c:144
int ReservedBackends
Definition: postmaster.c:219
void ProcSignalInit(int pss_idx)
Definition: procsignal.c:161
void RelationCacheInitializePhase3(void)
Definition: relcache.c:3975
void RelationCacheInitialize(void)
Definition: relcache.c:3870
void RelationCacheInitializePhase2(void)
Definition: relcache.c:3916
char * GetDatabasePath(Oid dbNode, Oid spcNode)
Definition: relpath.c:110
void ReleaseAuxProcessResources(bool isCommit)
Definition: resowner.c:907
ResourceOwner CurrentResourceOwner
Definition: resowner.c:146
void CreateAuxProcessResourceOwner(void)
Definition: resowner.c:887
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:250
void InvalidateCatalogSnapshot(void)
Definition: snapmgr.c:456
void CheckDeadLockAlert(void)
Definition: proc.c:1847
void InitProcessPhase2(void)
Definition: proc.c:480
bool HaveNFreeProcs(int n)
Definition: proc.c:659
Oid databaseId
Definition: proc.h:192
bool superuser(void)
Definition: superuser.c:46
void InitCatalogCache(void)
Definition: syscache.c:1067
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:2925
int XactIsoLevel
Definition: xact.c:78
void SetCurrentStatementStartTimestamp(void)
Definition: xact.c:886
void CommitTransactionCommand(void)
Definition: xact.c:3022
#define XACT_READ_COMMITTED
Definition: xact.h:37
void StartupXLOG(void)
Definition: xlog.c:4877
void ShutdownXLOG(int code, Datum arg)
Definition: xlog.c:6004

References am_db_walsender, am_walsender, Assert(), 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_rolreplication(), HaveNFreeProcs(), HeapTupleIsValid, IDLE_IN_TRANSACTION_SESSION_TIMEOUT, IDLE_SESSION_TIMEOUT, IDLE_STATS_UPDATE_TIMEOUT, IdleInTransactionSessionTimeoutHandler(), IdleSessionTimeoutHandler(), IdleStatsUpdateTimeoutHandler(), InitCatalogCache(), initialize_acl(), InitializeClientEncoding(), InitializeSearchPath(), InitializeSession(), InitializeSessionUserId(), InitializeSessionUserIdStandalone(), InitPlanCache(), InitProcessPhase2(), InvalidateCatalogSnapshot(), InvalidBackendId, IsAutoVacuumLauncherProcess(), IsAutoVacuumWorkerProcess(), IsBackgroundWorker, IsBinaryUpgrade, IsBootstrapProcessingMode, IsUnderPostmaster, LOCK_TIMEOUT, LockSharedObject(), LockTimeoutHandler(), MaxBackends, MyBackendId, MyDatabaseId, MyDatabaseTableSpace, MyProc, MyProcPort, NAMEDATALEN, NameStr, OidIsValid, PerformAuthentication(), pfree(), pg_usleep(), pgstat_before_server_shutdown(), pgstat_beinit(), pgstat_bestart(), PostAuthDelay, process_settings(), process_startup_options(), ProcSignalInit(), RegisterTimeout(), RelationCacheInitialize(), RelationCacheInitializePhase2(), RelationCacheInitializePhase3(), ReleaseAuxProcessResources(), ReservedBackends, RowExclusiveLock, SetCurrentStatementStartTimestamp(), SetDatabasePath(), SharedInvalBackendInit(), ShutdownPostgres(), ShutdownXLOG(), StartTransactionCommand(), StartupXLOG(), STATEMENT_TIMEOUT, StatementTimeoutHandler(), strlcpy(), superuser(), 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 1281 of file postinit.c.

1282 {
1283 #ifdef HAVE_SETSID
1284  /* try to signal whole process group */
1285  kill(-MyProcPid, SIGINT);
1286 #endif
1287  kill(MyProcPid, SIGINT);
1288 }
int MyProcPid
Definition: globals.c:44
#define kill(pid, sig)
Definition: win32_port.h:464

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  (errmsg("could not load pg_hba.conf")));
221  }
222 
223  if (!load_ident())
224  {
225  /*
226  * It is ok to continue if we fail to load the IDENT file, although it
227  * means that you cannot log in using any of the authentication
228  * methods that need a user name mapping. load_ident() already logged
229  * the details of error to the log.
230  */
231  }
232 #endif
233 
234  /*
235  * Set up a timeout in case a buggy or malicious client fails to respond
236  * during authentication. Since we're inside a transaction and might do
237  * database access, we have to use the statement_timeout infrastructure.
238  */
240 
241  /*
242  * Now perform authentication exchange.
243  */
244  set_ps_display("authentication");
245  ClientAuthentication(port); /* might not return, if failure */
246 
247  /*
248  * Done with authentication. Disable the timeout, and log if needed.
249  */
251 
252  if (Log_connections)
253  {
254  StringInfoData logmsg;
255 
256  initStringInfo(&logmsg);
257  if (am_walsender)
258  appendStringInfo(&logmsg, _("replication connection authorized: user=%s"),
259  port->user_name);
260  else
261  appendStringInfo(&logmsg, _("connection authorized: user=%s"),
262  port->user_name);
263  if (!am_walsender)
264  appendStringInfo(&logmsg, _(" database=%s"), port->database_name);
265 
266  if (port->application_name != NULL)
267  appendStringInfo(&logmsg, _(" application_name=%s"),
268  port->application_name);
269 
270 #ifdef USE_SSL
271  if (port->ssl_in_use)
272  appendStringInfo(&logmsg, _(" SSL enabled (protocol=%s, cipher=%s, bits=%d)"),
276 #endif
277 #ifdef ENABLE_GSS
278  if (port->gss)
279  {
280  const char *princ = be_gssapi_get_princ(port);
281 
282  if (princ)
283  appendStringInfo(&logmsg,
284  _(" GSS (authenticated=%s, encrypted=%s, principal=%s)"),
285  be_gssapi_get_auth(port) ? _("yes") : _("no"),
286  be_gssapi_get_enc(port) ? _("yes") : _("no"),
287  princ);
288  else
289  appendStringInfo(&logmsg,
290  _(" GSS (authenticated=%s, encrypted=%s)"),
291  be_gssapi_get_auth(port) ? _("yes") : _("no"),
292  be_gssapi_get_enc(port) ? _("yes") : _("no"));
293  }
294 #endif
295 
296  ereport(LOG, errmsg_internal("%s", logmsg.data));
297  pfree(logmsg.data);
298  }
299 
300  set_ps_display("startup");
301 
302  ClientAuthInProgress = false; /* client_min_messages is active now */
303 }
void ClientAuthentication(Port *port)
Definition: auth.c:385
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:991
#define _(x)
Definition: elog.c:89
#define LOG
Definition: elog.h:25
bool load_ident(void)
Definition: hba.c:2586
bool load_hba(void)
Definition: hba.c:2207
MemoryContext TopMemoryContext
Definition: mcxt.c:48
MemoryContext PostmasterContext
Definition: mcxt.c:50
#define AllocSetContextCreate
Definition: memutils.h:173
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:197
static int port
Definition: pg_regress.c:92
bool Log_connections
Definition: postmaster.c:242
bool ClientAuthInProgress
Definition: postmaster.c:358
int AuthenticationTimeout
Definition: postmaster.c:239
void set_ps_display(const char *activity)
Definition: ps_status.c:349
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, 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 493 of file postinit.c.

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

1191 {
1192  Relation relsetting;
1193  Snapshot snapshot;
1194 
1195  if (!IsUnderPostmaster)
1196  return;
1197 
1198  relsetting = table_open(DbRoleSettingRelationId, AccessShareLock);
1199 
1200  /* read all the settings under the same snapshot for efficiency */
1201  snapshot = RegisterSnapshot(GetCatalogSnapshot(DbRoleSettingRelationId));
1202 
1203  /* Later settings are ignored if set earlier. */
1204  ApplySetting(snapshot, databaseid, roleid, relsetting, PGC_S_DATABASE_USER);
1205  ApplySetting(snapshot, InvalidOid, roleid, relsetting, PGC_S_USER);
1206  ApplySetting(snapshot, databaseid, InvalidOid, relsetting, PGC_S_DATABASE);
1207  ApplySetting(snapshot, InvalidOid, InvalidOid, relsetting, PGC_S_GLOBAL);
1208 
1209  UnregisterSnapshot(snapshot);
1210  table_close(relsetting, AccessShareLock);
1211 }
@ PGC_S_GLOBAL
Definition: guc.h:111
@ PGC_S_DATABASE
Definition: guc.h:112
@ PGC_S_DATABASE_USER
Definition: guc.h:114
@ PGC_S_USER
Definition: guc.h:113
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:386
void UnregisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:869
Snapshot RegisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:827

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

1126 {
1127  GucContext gucctx;
1128  ListCell *gucopts;
1129 
1130  gucctx = am_superuser ? PGC_SU_BACKEND : PGC_BACKEND;
1131 
1132  /*
1133  * First process any command-line switches that were included in the
1134  * startup packet, if we are in a regular backend.
1135  */
1136  if (port->cmdline_options != NULL)
1137  {
1138  /*
1139  * The maximum possible number of commandline arguments that could
1140  * come from port->cmdline_options is (strlen + 1) / 2; see
1141  * pg_split_opts().
1142  */
1143  char **av;
1144  int maxac;
1145  int ac;
1146 
1147  maxac = 2 + (strlen(port->cmdline_options) + 1) / 2;
1148 
1149  av = (char **) palloc(maxac * sizeof(char *));
1150  ac = 0;
1151 
1152  av[ac++] = "postgres";
1153 
1154  pg_split_opts(av, &ac, port->cmdline_options);
1155 
1156  av[ac] = NULL;
1157 
1158  Assert(ac < maxac);
1159 
1160  (void) process_postgres_switches(ac, av, gucctx, NULL);
1161  }
1162 
1163  /*
1164  * Process any additional GUC variable settings passed in startup packet.
1165  * These are handled exactly like command-line variables.
1166  */
1167  gucopts = list_head(port->guc_options);
1168  while (gucopts)
1169  {
1170  char *name;
1171  char *value;
1172 
1173  name = lfirst(gucopts);
1174  gucopts = lnext(port->guc_options, gucopts);
1175 
1176  value = lfirst(gucopts);
1177  gucopts = lnext(port->guc_options, gucopts);
1178 
1180  }
1181 }
@ PGC_S_CLIENT
Definition: guc.h:115
GucContext
Definition: guc.h:69
@ PGC_SU_BACKEND
Definition: guc.h:73
static struct @151 value
void * palloc(Size size)
Definition: mcxt.c:1068
#define lfirst(lc)
Definition: pg_list.h:169
static ListCell * list_head(const List *l)
Definition: pg_list.h:125
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:322
void process_postgres_switches(int argc, char *argv[], GucContext ctx, const char **dbname)
Definition: postgres.c:3706
void pg_split_opts(char **argv, int *argcp, const char *optstr)
Definition: postinit.c:493
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 1224 of file postinit.c.

1225 {
1226  /* Make sure we've killed any active transaction */
1228 
1229  /*
1230  * User locks are not released by transaction end, so be sure to release
1231  * them explicitly.
1232  */
1234 
1235  /*
1236  * temp debugging aid to analyze 019_replslot_limit failures
1237  *
1238  * If an error were thrown outside of a transaction nothing up to now
1239  * would have released lwlocks. We probably will add an
1240  * LWLockReleaseAll(). But for now make it easier to understand such cases
1241  * by warning if any lwlocks are held.
1242  */
1243 #ifdef USE_ASSERT_CHECKING
1244  {
1245  int held_lwlocks = LWLockHeldCount();
1246 
1247  if (held_lwlocks)
1248  elog(WARNING, "holding %d lwlocks at the end of ShutdownPostgres()",
1249  held_lwlocks);
1250  }
1251 #endif
1252 }
void LockReleaseAll(LOCKMETHODID lockmethodid, bool allLocks)
Definition: lock.c:2180
#define USER_LOCKMETHOD
Definition: lock.h:131
static LWLockHandle held_lwlocks[MAX_SIMUL_LWLOCKS]
Definition: lwlock.c:223
int LWLockHeldCount(void)
Definition: lwlock.c:1948
void AbortOutOfAnyTransaction(void)
Definition: xact.c:4662

References AbortOutOfAnyTransaction(), elog, held_lwlocks, LockReleaseAll(), LWLockHeldCount(), USER_LOCKMETHOD, and WARNING.

Referenced by InitPostgres().

◆ StatementTimeoutHandler()

static void StatementTimeoutHandler ( void  )
static

Definition at line 1259 of file postinit.c.

1260 {
1261  int sig = SIGINT;
1262 
1263  /*
1264  * During authentication the timeout is used to deal with
1265  * authentication_timeout - we want to quit in response to such timeouts.
1266  */
1268  sig = SIGTERM;
1269 
1270 #ifdef HAVE_SETSID
1271  /* try to signal whole process group */
1272  kill(-MyProcPid, sig);
1273 #endif
1274  kill(MyProcPid, sig);
1275 }
static int sig
Definition: pg_ctl.c:84

References ClientAuthInProgress, kill, MyProcPid, and sig.

Referenced by InitPostgres().

◆ ThereIsAtLeastOneRole()

static bool ThereIsAtLeastOneRole ( void  )
static

Definition at line 1326 of file postinit.c.

1327 {
1328  Relation pg_authid_rel;
1329  TableScanDesc scan;
1330  bool result;
1331 
1332  pg_authid_rel = table_open(AuthIdRelationId, AccessShareLock);
1333 
1334  scan = table_beginscan_catalog(pg_authid_rel, 0, NULL);
1335  result = (heap_getnext(scan, ForwardScanDirection) != NULL);
1336 
1337  table_endscan(scan);
1338  table_close(pg_authid_rel, AccessShareLock);
1339 
1340  return result;
1341 }
HeapTuple heap_getnext(TableScanDesc sscan, ScanDirection direction)
Definition: heapam.c:1296
@ ForwardScanDirection
Definition: sdir.h:26
TableScanDesc table_beginscan_catalog(Relation relation, int nkeys, struct ScanKeyData *key)
Definition: tableam.c:112
static void table_endscan(TableScanDesc scan)
Definition: tableam.h:993

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

Referenced by InitPostgres().