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 "catalog/catalog.h"
#include "catalog/namespace.h"
#include "catalog/pg_authid.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/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/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 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 511 of file postinit.c.

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

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

512 {
513  Assert(MyProc != NULL);
514 
515  /*
516  * Initialize our input/output/debugging file descriptors.
517  */
518  DebugFileOpen();
519 
520  /*
521  * Initialize file access. Done early so other subsystems can access
522  * files.
523  */
524  InitFileAccess();
525 
526  /*
527  * Initialize statistics reporting. This needs to happen early to ensure
528  * that pgstat's shutdown callback runs after the shutdown callbacks of
529  * all subsystems that can produce stats (like e.g. transaction commits
530  * can).
531  */
533 
534  /* Do local initialization of storage and buffer managers */
535  InitSync();
536  smgrinit();
538 
539  /*
540  * Initialize temporary file access after pgstat, so that the temporary
541  * file shutdown hook can report temporary file statistics.
542  */
544 }
PGPROC * MyProc
Definition: proc.c:68
void InitBufferPoolAccess(void)
Definition: bufmgr.c:2596
void pgstat_initialize(void)
Definition: pgstat.c:3026
void DebugFileOpen(void)
Definition: elog.c:1922
void smgrinit(void)
Definition: smgr.c:111
#define Assert(condition)
Definition: c.h:804
void InitSync(void)
Definition: sync.c:128
void InitTemporaryFileAccess(void)
Definition: fd.c:912
void InitFileAccess(void)
Definition: fd.c:882

◆ CheckMyDatabase()

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

Definition at line 305 of file postinit.c.

References ACL_CONNECT, ACLCHECK_OK, check_strxfrm_bug(), CountDBConnections(), DATABASEOID, elog, ereport, errcode(), errdetail(), errhint(), errmsg(), ERROR, FATAL, GetDatabaseEncodingName(), GETSTRUCT, GetUserId(), HeapTupleIsValid, IsAutoVacuumWorkerProcess(), IsUnderPostmaster, MyDatabaseId, NameStr, ObjectIdGetDatum, pg_database_aclcheck(), pg_perm_setlocale(), PGC_BACKEND, PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT, PGC_S_OVERRIDE, ReleaseSysCache(), SearchSysCache1(), SetConfigOption(), and SetDatabaseEncoding().

Referenced by InitPostgres().

306 {
307  HeapTuple tup;
308  Form_pg_database dbform;
309  char *collate;
310  char *ctype;
311 
312  /* Fetch our pg_database row normally, via syscache */
314  if (!HeapTupleIsValid(tup))
315  elog(ERROR, "cache lookup failed for database %u", MyDatabaseId);
316  dbform = (Form_pg_database) GETSTRUCT(tup);
317 
318  /* This recheck is strictly paranoia */
319  if (strcmp(name, NameStr(dbform->datname)) != 0)
320  ereport(FATAL,
321  (errcode(ERRCODE_UNDEFINED_DATABASE),
322  errmsg("database \"%s\" has disappeared from pg_database",
323  name),
324  errdetail("Database OID %u now seems to belong to \"%s\".",
325  MyDatabaseId, NameStr(dbform->datname))));
326 
327  /*
328  * Check permissions to connect to the database.
329  *
330  * These checks are not enforced when in standalone mode, so that there is
331  * a way to recover from disabling all access to all databases, for
332  * example "UPDATE pg_database SET datallowconn = false;".
333  *
334  * We do not enforce them for autovacuum worker processes either.
335  */
337  {
338  /*
339  * Check that the database is currently allowing connections.
340  */
341  if (!dbform->datallowconn && !override_allow_connections)
342  ereport(FATAL,
343  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
344  errmsg("database \"%s\" is not currently accepting connections",
345  name)));
346 
347  /*
348  * Check privilege to connect to the database. (The am_superuser test
349  * is redundant, but since we have the flag, might as well check it
350  * and save a few cycles.)
351  */
352  if (!am_superuser &&
355  ereport(FATAL,
356  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
357  errmsg("permission denied for database \"%s\"", name),
358  errdetail("User does not have CONNECT privilege.")));
359 
360  /*
361  * Check connection limit for this database.
362  *
363  * There is a race condition here --- we create our PGPROC before
364  * checking for other PGPROCs. If two backends did this at about the
365  * same time, they might both think they were over the limit, while
366  * ideally one should succeed and one fail. Getting that to work
367  * exactly seems more trouble than it is worth, however; instead we
368  * just document that the connection limit is approximate.
369  */
370  if (dbform->datconnlimit >= 0 &&
371  !am_superuser &&
372  CountDBConnections(MyDatabaseId) > dbform->datconnlimit)
373  ereport(FATAL,
374  (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
375  errmsg("too many connections for database \"%s\"",
376  name)));
377  }
378 
379  /*
380  * OK, we're golden. Next to-do item is to save the encoding info out of
381  * the pg_database tuple.
382  */
383  SetDatabaseEncoding(dbform->encoding);
384  /* Record it as a GUC internal option, too */
385  SetConfigOption("server_encoding", GetDatabaseEncodingName(),
387  /* If we have no other source of client_encoding, use server encoding */
388  SetConfigOption("client_encoding", GetDatabaseEncodingName(),
390 
391  /* assign locale variables */
392  collate = NameStr(dbform->datcollate);
393  ctype = NameStr(dbform->datctype);
394 
395  if (pg_perm_setlocale(LC_COLLATE, collate) == NULL)
396  ereport(FATAL,
397  (errmsg("database locale is incompatible with operating system"),
398  errdetail("The database was initialized with LC_COLLATE \"%s\", "
399  " which is not recognized by setlocale().", collate),
400  errhint("Recreate the database with another locale or install the missing locale.")));
401 
402  if (pg_perm_setlocale(LC_CTYPE, ctype) == NULL)
403  ereport(FATAL,
404  (errmsg("database locale is incompatible with operating system"),
405  errdetail("The database was initialized with LC_CTYPE \"%s\", "
406  " which is not recognized by setlocale().", ctype),
407  errhint("Recreate the database with another locale or install the missing locale.")));
408 
409  /* Make the locale settings visible as GUC variables, too */
410  SetConfigOption("lc_collate", collate, PGC_INTERNAL, PGC_S_OVERRIDE);
411  SetConfigOption("lc_ctype", ctype, PGC_INTERNAL, PGC_S_OVERRIDE);
412 
414 
415  ReleaseSysCache(tup);
416 }
int errhint(const char *fmt,...)
Definition: elog.c:1156
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
Oid GetUserId(void)
Definition: miscinit.c:495
FormData_pg_database * Form_pg_database
Definition: pg_database.h:81
int errcode(int sqlerrcode)
Definition: elog.c:698
char * pg_perm_setlocale(int category, const char *locale)
Definition: pg_locale.c:143
int CountDBConnections(Oid databaseid)
Definition: procarray.c:3561
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
#define FATAL
Definition: elog.h:49
void check_strxfrm_bug(void)
Definition: pg_locale.c:1187
void SetConfigOption(const char *name, const char *value, GucContext context, GucSource source)
Definition: guc.c:8123
bool IsUnderPostmaster
Definition: globals.c:112
int errdetail(const char *fmt,...)
Definition: elog.c:1042
bool IsAutoVacuumWorkerProcess(void)
Definition: autovacuum.c:3410
#define ACL_CONNECT
Definition: parsenodes.h:94
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1150
void SetDatabaseEncoding(int encoding)
Definition: mbutils.c:1104
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1198
Oid MyDatabaseId
Definition: globals.c:88
#define ereport(elevel,...)
Definition: elog.h:157
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
AclResult pg_database_aclcheck(Oid db_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4708
const char * GetDatabaseEncodingName(void)
Definition: mbutils.c:1216
const char * name
Definition: encode.c:561
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
#define NameStr(name)
Definition: c.h:681

◆ ClientCheckTimeoutHandler()

static void ClientCheckTimeoutHandler ( void  )
static

Definition at line 1241 of file postinit.c.

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

Referenced by InitPostgres().

1242 {
1244  InterruptPending = true;
1245  SetLatch(MyLatch);
1246 }
void SetLatch(Latch *latch)
Definition: latch.c:567
volatile sig_atomic_t InterruptPending
Definition: globals.c:30
struct Latch * MyLatch
Definition: globals.c:57
volatile sig_atomic_t CheckClientConnectionPending
Definition: globals.c:33

◆ GetDatabaseTuple()

static HeapTuple GetDatabaseTuple ( const char *  dbname)
static

Definition at line 96 of file postinit.c.

References AccessShareLock, BTEqualStrategyNumber, criticalSharedRelcachesBuilt, CStringGetDatum, heap_copytuple(), HeapTupleIsValid, sort-test::key, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by InitPostgres().

97 {
98  HeapTuple tuple;
99  Relation relation;
100  SysScanDesc scan;
101  ScanKeyData key[1];
102 
103  /*
104  * form a scan key
105  */
106  ScanKeyInit(&key[0],
107  Anum_pg_database_datname,
108  BTEqualStrategyNumber, F_NAMEEQ,
110 
111  /*
112  * Open pg_database and fetch a tuple. Force heap scan if we haven't yet
113  * built the critical shared relcache entries (i.e., we're starting up
114  * without a shared relcache cache file).
115  */
116  relation = table_open(DatabaseRelationId, AccessShareLock);
117  scan = systable_beginscan(relation, DatabaseNameIndexId,
119  NULL,
120  1, key);
121 
122  tuple = systable_getnext(scan);
123 
124  /* Must copy tuple before releasing buffer */
125  if (HeapTupleIsValid(tuple))
126  tuple = heap_copytuple(tuple);
127 
128  /* all done */
129  systable_endscan(scan);
130  table_close(relation, AccessShareLock);
131 
132  return tuple;
133 }
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:680
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:595
#define AccessShareLock
Definition: lockdefs.h:36
bool criticalSharedRelcachesBuilt
Definition: relcache.c:143
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:383
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
#define CStringGetDatum(X)
Definition: postgres.h:622
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
char * dbname
Definition: streamutil.c:51
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ GetDatabaseTupleByOid()

static HeapTuple GetDatabaseTupleByOid ( Oid  dboid)
static

Definition at line 139 of file postinit.c.

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().

140 {
141  HeapTuple tuple;
142  Relation relation;
143  SysScanDesc scan;
144  ScanKeyData key[1];
145 
146  /*
147  * form a scan key
148  */
149  ScanKeyInit(&key[0],
150  Anum_pg_database_oid,
151  BTEqualStrategyNumber, F_OIDEQ,
152  ObjectIdGetDatum(dboid));
153 
154  /*
155  * Open pg_database and fetch a tuple. Force heap scan if we haven't yet
156  * built the critical shared relcache entries (i.e., we're starting up
157  * without a shared relcache cache file).
158  */
159  relation = table_open(DatabaseRelationId, AccessShareLock);
160  scan = systable_beginscan(relation, DatabaseOidIndexId,
162  NULL,
163  1, key);
164 
165  tuple = systable_getnext(scan);
166 
167  /* Must copy tuple before releasing buffer */
168  if (HeapTupleIsValid(tuple))
169  tuple = heap_copytuple(tuple);
170 
171  /* all done */
172  systable_endscan(scan);
173  table_close(relation, AccessShareLock);
174 
175  return tuple;
176 }
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:680
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:595
#define AccessShareLock
Definition: lockdefs.h:36
bool criticalSharedRelcachesBuilt
Definition: relcache.c:143
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:383
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ IdleInTransactionSessionTimeoutHandler()

static void IdleInTransactionSessionTimeoutHandler ( void  )
static

Definition at line 1225 of file postinit.c.

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

Referenced by InitPostgres().

1226 {
1228  InterruptPending = true;
1229  SetLatch(MyLatch);
1230 }
void SetLatch(Latch *latch)
Definition: latch.c:567
volatile sig_atomic_t IdleInTransactionSessionTimeoutPending
Definition: globals.c:35
volatile sig_atomic_t InterruptPending
Definition: globals.c:30
struct Latch * MyLatch
Definition: globals.c:57

◆ IdleSessionTimeoutHandler()

static void IdleSessionTimeoutHandler ( void  )
static

Definition at line 1233 of file postinit.c.

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

Referenced by InitPostgres().

1234 {
1236  InterruptPending = true;
1237  SetLatch(MyLatch);
1238 }
volatile sig_atomic_t IdleSessionTimeoutPending
Definition: globals.c:36
void SetLatch(Latch *latch)
Definition: latch.c:567
volatile sig_atomic_t InterruptPending
Definition: globals.c:30
struct Latch * MyLatch
Definition: globals.c:57

◆ InitializeMaxBackends()

void InitializeMaxBackends ( void  )

Definition at line 489 of file postinit.c.

References Assert, autovacuum_max_workers, elog, ERROR, MAX_BACKENDS, max_wal_senders, max_worker_processes, MaxBackends, and MaxConnections.

Referenced by BootstrapModeMain(), PostgresSingleUserMain(), and PostmasterMain().

490 {
491  Assert(MaxBackends == 0);
492 
493  /* the extra unit accounts for the autovacuum launcher */
496 
497  /* internal error because the values were all checked previously */
499  elog(ERROR, "too many backends configured");
500 }
#define ERROR
Definition: elog.h:46
#define MAX_BACKENDS
Definition: postmaster.h:76
int MaxBackends
Definition: globals.c:139
int max_wal_senders
Definition: walsender.c:121
int MaxConnections
Definition: globals.c:136
int autovacuum_max_workers
Definition: autovacuum.c:115
#define Assert(condition)
Definition: c.h:804
#define elog(elevel,...)
Definition: elog.h:232
int max_worker_processes
Definition: globals.c:137

◆ InitPostgres()

void InitPostgres ( const char *  in_dbname,
Oid  dboid,
const char *  username,
Oid  useroid,
char *  out_dbname,
bool  override_allow_connections 
)

Definition at line 572 of file postinit.c.

References am_db_walsender, am_walsender, Assert, before_shmem_exit(), CAC_SUPERUSER, Port::canAcceptConnections, 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, IdleInTransactionSessionTimeoutHandler(), IdleSessionTimeoutHandler(), 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(), pg_usleep(), pgstat_beinit(), pgstat_bestart(), PostAuthDelay, process_settings(), process_startup_options(), ProcSignalInit(), RecoveryInProgress(), RegisterTimeout(), RelationCacheInitialize(), RelationCacheInitializePhase2(), RelationCacheInitializePhase3(), ReleaseAuxProcessResources(), ReservedBackends, RowExclusiveLock, SetCurrentStatementStartTimestamp(), SetDatabasePath(), SharedInvalBackendInit(), ShutdownPostgres(), ShutdownXLOG(), StartTransactionCommand(), StartupXLOG(), STATEMENT_TIMEOUT, StatementTimeoutHandler(), strlcpy(), superuser(), ThereIsAtLeastOneRole(), ValidatePgVersion(), WARNING, XACT_READ_COMMITTED, and XactIsoLevel.

Referenced by AutoVacLauncherMain(), AutoVacWorkerMain(), BackgroundWorkerInitializeConnection(), BackgroundWorkerInitializeConnectionByOid(), BootstrapModeMain(), and PostgresMain().

574 {
575  bool bootstrap = IsBootstrapProcessingMode();
576  bool am_superuser;
577  char *fullpath;
578  char dbname[NAMEDATALEN];
579 
580  elog(DEBUG3, "InitPostgres");
581 
582  /*
583  * Add my PGPROC struct to the ProcArray.
584  *
585  * Once I have done this, I am visible to other backends!
586  */
588 
589  /*
590  * Initialize my entry in the shared-invalidation manager's array of
591  * per-backend data.
592  *
593  * Sets up MyBackendId, a unique backend identifier.
594  */
596 
597  SharedInvalBackendInit(false);
598 
599  if (MyBackendId > MaxBackends || MyBackendId <= 0)
600  elog(FATAL, "bad backend ID: %d", MyBackendId);
601 
602  /* Now that we have a BackendId, we can participate in ProcSignal */
604 
605  /*
606  * Also set up timeout handlers needed for backend operation. We need
607  * these in every case except bootstrap.
608  */
609  if (!bootstrap)
610  {
618  }
619 
620  /*
621  * Initialize local process's access to XLOG.
622  */
623  if (IsUnderPostmaster)
624  {
625  /*
626  * The postmaster already started the XLOG machinery, but we need to
627  * call InitXLOGAccess(), if the system isn't in hot-standby mode.
628  * This is handled by calling RecoveryInProgress and ignoring the
629  * result.
630  */
631  (void) RecoveryInProgress();
632  }
633  else
634  {
635  /*
636  * We are either a bootstrap process or a standalone backend. Either
637  * way, start up the XLOG machinery, and register to have it closed
638  * down at exit.
639  *
640  * We don't yet have an aux-process resource owner, but StartupXLOG
641  * and ShutdownXLOG will need one. Hence, create said resource owner
642  * (and register a callback to clean it up after ShutdownXLOG runs).
643  */
645 
646  StartupXLOG();
647  /* Release (and warn about) any buffer pins leaked in StartupXLOG */
649  /* Reset CurrentResourceOwner to nothing for the moment */
650  CurrentResourceOwner = NULL;
651 
652  /*
653  * Use before_shmem_exit() so that ShutdownXLOG() can rely on DSM
654  * segments etc to work (which in turn is required for pgstats).
655  */
657  }
658 
659  /*
660  * Initialize the relation cache and the system catalog caches. Note that
661  * no catalog access happens here; we only set up the hashtable structure.
662  * We must do this before starting a transaction because transaction abort
663  * would try to touch these hashtables.
664  */
667  InitPlanCache();
668 
669  /* Initialize portal manager */
671 
672  /* Initialize status reporting */
673  if (!bootstrap)
674  pgstat_beinit();
675 
676  /*
677  * Load relcache entries for the shared system catalogs. This must create
678  * at least entries for pg_database and catalogs used for authentication.
679  */
681 
682  /*
683  * Set up process-exit callback to do pre-shutdown cleanup. This is the
684  * one of the first before_shmem_exit callbacks we register; thus, this
685  * will be one the last things we do before low-level modules like the
686  * buffer manager begin to close down. We need to have this in place
687  * before we begin our first transaction --- if we fail during the
688  * initialization transaction, as is entirely possible, we need the
689  * AbortTransaction call to clean up.
690  */
692 
693  /* The autovacuum launcher is done here */
695  {
696  /* report this backend in the PgBackendStatus array */
697  pgstat_bestart();
698 
699  return;
700  }
701 
702  /*
703  * Start a new transaction here before first access to db, and get a
704  * snapshot. We don't have a use for the snapshot itself, but we're
705  * interested in the secondary effect that it sets RecentGlobalXmin. (This
706  * is critical for anything that reads heap pages, because HOT may decide
707  * to prune them even if the process doesn't attempt to modify any
708  * tuples.)
709  *
710  * FIXME: This comment is inaccurate / the code buggy. A snapshot that is
711  * not pushed/active does not reliably prevent HOT pruning (->xmin could
712  * e.g. be cleared when cache invalidations are processed).
713  */
714  if (!bootstrap)
715  {
716  /* statement_timestamp must be set for timeouts to work correctly */
719 
720  /*
721  * transaction_isolation will have been set to the default by the
722  * above. If the default is "serializable", and we are in hot
723  * standby, we will fail if we don't change it to something lower.
724  * Fortunately, "read committed" is plenty good enough.
725  */
727 
728  (void) GetTransactionSnapshot();
729  }
730 
731  /*
732  * Perform client authentication if necessary, then figure out our
733  * postgres user ID, and see if we are a superuser.
734  *
735  * In standalone mode and in autovacuum worker processes, we use a fixed
736  * ID, otherwise we figure it out from the authenticated user name.
737  */
738  if (bootstrap || IsAutoVacuumWorkerProcess())
739  {
741  am_superuser = true;
742  }
743  else if (!IsUnderPostmaster)
744  {
746  am_superuser = true;
747  if (!ThereIsAtLeastOneRole())
749  (errcode(ERRCODE_UNDEFINED_OBJECT),
750  errmsg("no roles are defined in this database system"),
751  errhint("You should immediately run CREATE USER \"%s\" SUPERUSER;.",
752  username != NULL ? username : "postgres")));
753  }
754  else if (IsBackgroundWorker)
755  {
756  if (username == NULL && !OidIsValid(useroid))
757  {
759  am_superuser = true;
760  }
761  else
762  {
764  am_superuser = superuser();
765  }
766  }
767  else
768  {
769  /* normal multiuser case */
770  Assert(MyProcPort != NULL);
773  am_superuser = superuser();
774  }
775 
776  /*
777  * If we're trying to shut down, only superusers can connect, and new
778  * replication connections are not allowed.
779  */
780  if ((!am_superuser || am_walsender) &&
781  MyProcPort != NULL &&
783  {
784  if (am_walsender)
785  ereport(FATAL,
786  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
787  errmsg("new replication connections are not allowed during database shutdown")));
788  else
789  ereport(FATAL,
790  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
791  errmsg("must be superuser to connect during database shutdown")));
792  }
793 
794  /*
795  * Binary upgrades only allowed super-user connections
796  */
797  if (IsBinaryUpgrade && !am_superuser)
798  {
799  ereport(FATAL,
800  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
801  errmsg("must be superuser to connect in binary upgrade mode")));
802  }
803 
804  /*
805  * The last few connection slots are reserved for superusers. Replication
806  * connections are drawn from slots reserved with max_wal_senders and not
807  * limited by max_connections or superuser_reserved_connections.
808  */
809  if (!am_superuser && !am_walsender &&
810  ReservedBackends > 0 &&
812  ereport(FATAL,
813  (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
814  errmsg("remaining connection slots are reserved for non-replication superuser connections")));
815 
816  /* Check replication permissions needed for walsender processes. */
817  if (am_walsender)
818  {
819  Assert(!bootstrap);
820 
821  if (!superuser() && !has_rolreplication(GetUserId()))
822  ereport(FATAL,
823  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
824  errmsg("must be superuser or replication role to start walsender")));
825  }
826 
827  /*
828  * If this is a plain walsender only supporting physical replication, we
829  * don't want to connect to any particular database. Just finish the
830  * backend startup by processing any options from the startup packet, and
831  * we're done.
832  */
834  {
835  /* process any options passed in the startup packet */
836  if (MyProcPort != NULL)
837  process_startup_options(MyProcPort, am_superuser);
838 
839  /* Apply PostAuthDelay as soon as we've read all options */
840  if (PostAuthDelay > 0)
841  pg_usleep(PostAuthDelay * 1000000L);
842 
843  /* initialize client encoding */
845 
846  /* report this backend in the PgBackendStatus array */
847  pgstat_bestart();
848 
849  /* close the transaction we started above */
851 
852  return;
853  }
854 
855  /*
856  * Set up the global variables holding database id and default tablespace.
857  * But note we won't actually try to touch the database just yet.
858  *
859  * We take a shortcut in the bootstrap case, otherwise we have to look up
860  * the db's entry in pg_database.
861  */
862  if (bootstrap)
863  {
864  MyDatabaseId = TemplateDbOid;
865  MyDatabaseTableSpace = DEFAULTTABLESPACE_OID;
866  }
867  else if (in_dbname != NULL)
868  {
869  HeapTuple tuple;
870  Form_pg_database dbform;
871 
872  tuple = GetDatabaseTuple(in_dbname);
873  if (!HeapTupleIsValid(tuple))
874  ereport(FATAL,
875  (errcode(ERRCODE_UNDEFINED_DATABASE),
876  errmsg("database \"%s\" does not exist", in_dbname)));
877  dbform = (Form_pg_database) GETSTRUCT(tuple);
878  MyDatabaseId = dbform->oid;
879  MyDatabaseTableSpace = dbform->dattablespace;
880  /* take database name from the caller, just for paranoia */
881  strlcpy(dbname, in_dbname, sizeof(dbname));
882  }
883  else if (OidIsValid(dboid))
884  {
885  /* caller specified database by OID */
886  HeapTuple tuple;
887  Form_pg_database dbform;
888 
889  tuple = GetDatabaseTupleByOid(dboid);
890  if (!HeapTupleIsValid(tuple))
891  ereport(FATAL,
892  (errcode(ERRCODE_UNDEFINED_DATABASE),
893  errmsg("database %u does not exist", dboid)));
894  dbform = (Form_pg_database) GETSTRUCT(tuple);
895  MyDatabaseId = dbform->oid;
896  MyDatabaseTableSpace = dbform->dattablespace;
897  Assert(MyDatabaseId == dboid);
898  strlcpy(dbname, NameStr(dbform->datname), sizeof(dbname));
899  /* pass the database name back to the caller */
900  if (out_dbname)
901  strcpy(out_dbname, dbname);
902  }
903  else
904  {
905  /*
906  * If this is a background worker not bound to any particular
907  * database, we're done now. Everything that follows only makes sense
908  * if we are bound to a specific database. We do need to close the
909  * transaction we started before returning.
910  */
911  if (!bootstrap)
912  {
913  pgstat_bestart();
915  }
916  return;
917  }
918 
919  /*
920  * Now, take a writer's lock on the database we are trying to connect to.
921  * If there is a concurrently running DROP DATABASE on that database, this
922  * will block us until it finishes (and has committed its update of
923  * pg_database).
924  *
925  * Note that the lock is not held long, only until the end of this startup
926  * transaction. This is OK since we will advertise our use of the
927  * database in the ProcArray before dropping the lock (in fact, that's the
928  * next thing to do). Anyone trying a DROP DATABASE after this point will
929  * see us in the array once they have the lock. Ordering is important for
930  * this because we don't want to advertise ourselves as being in this
931  * database until we have the lock; otherwise we create what amounts to a
932  * deadlock with CountOtherDBBackends().
933  *
934  * Note: use of RowExclusiveLock here is reasonable because we envision
935  * our session as being a concurrent writer of the database. If we had a
936  * way of declaring a session as being guaranteed-read-only, we could use
937  * AccessShareLock for such sessions and thereby not conflict against
938  * CREATE DATABASE.
939  */
940  if (!bootstrap)
941  LockSharedObject(DatabaseRelationId, MyDatabaseId, 0,
943 
944  /*
945  * Now we can mark our PGPROC entry with the database ID.
946  *
947  * We assume this is an atomic store so no lock is needed; though actually
948  * things would work fine even if it weren't atomic. Anyone searching the
949  * ProcArray for this database's ID should hold the database lock, so they
950  * would not be executing concurrently with this store. A process looking
951  * for another database's ID could in theory see a chance match if it read
952  * a partially-updated databaseId value; but as long as all such searches
953  * wait and retry, as in CountOtherDBBackends(), they will certainly see
954  * the correct value on their next try.
955  */
957 
958  /*
959  * We established a catalog snapshot while reading pg_authid and/or
960  * pg_database; but until we have set up MyDatabaseId, we won't react to
961  * incoming sinval messages for unshared catalogs, so we won't realize it
962  * if the snapshot has been invalidated. Assume it's no good anymore.
963  */
965 
966  /*
967  * Recheck pg_database to make sure the target database hasn't gone away.
968  * If there was a concurrent DROP DATABASE, this ensures we will die
969  * cleanly without creating a mess.
970  */
971  if (!bootstrap)
972  {
973  HeapTuple tuple;
974 
975  tuple = GetDatabaseTuple(dbname);
976  if (!HeapTupleIsValid(tuple) ||
977  MyDatabaseId != ((Form_pg_database) GETSTRUCT(tuple))->oid ||
978  MyDatabaseTableSpace != ((Form_pg_database) GETSTRUCT(tuple))->dattablespace)
979  ereport(FATAL,
980  (errcode(ERRCODE_UNDEFINED_DATABASE),
981  errmsg("database \"%s\" does not exist", dbname),
982  errdetail("It seems to have just been dropped or renamed.")));
983  }
984 
985  /*
986  * Now we should be able to access the database directory safely. Verify
987  * it's there and looks reasonable.
988  */
990 
991  if (!bootstrap)
992  {
993  if (access(fullpath, F_OK) == -1)
994  {
995  if (errno == ENOENT)
996  ereport(FATAL,
997  (errcode(ERRCODE_UNDEFINED_DATABASE),
998  errmsg("database \"%s\" does not exist",
999  dbname),
1000  errdetail("The database subdirectory \"%s\" is missing.",
1001  fullpath)));
1002  else
1003  ereport(FATAL,
1005  errmsg("could not access directory \"%s\": %m",
1006  fullpath)));
1007  }
1008 
1009  ValidatePgVersion(fullpath);
1010  }
1011 
1012  SetDatabasePath(fullpath);
1013 
1014  /*
1015  * It's now possible to do real access to the system catalogs.
1016  *
1017  * Load relcache entries for the system catalogs. This must create at
1018  * least the minimum set of "nailed-in" cache entries.
1019  */
1021 
1022  /* set up ACL framework (so CheckMyDatabase can check permissions) */
1023  initialize_acl();
1024 
1025  /*
1026  * Re-read the pg_database row for our database, check permissions and set
1027  * up database-specific GUC settings. We can't do this until all the
1028  * database-access infrastructure is up. (Also, it wants to know if the
1029  * user is a superuser, so the above stuff has to happen first.)
1030  */
1031  if (!bootstrap)
1032  CheckMyDatabase(dbname, am_superuser, override_allow_connections);
1033 
1034  /*
1035  * Now process any command-line switches and any additional GUC variable
1036  * settings passed in the startup packet. We couldn't do this before
1037  * because we didn't know if client is a superuser.
1038  */
1039  if (MyProcPort != NULL)
1040  process_startup_options(MyProcPort, am_superuser);
1041 
1042  /* Process pg_db_role_setting options */
1044 
1045  /* Apply PostAuthDelay as soon as we've read all options */
1046  if (PostAuthDelay > 0)
1047  pg_usleep(PostAuthDelay * 1000000L);
1048 
1049  /*
1050  * Initialize various default states that can't be set up until we've
1051  * selected the active user and gotten the right GUC settings.
1052  */
1053 
1054  /* set default namespace search path */
1056 
1057  /* initialize client encoding */
1059 
1060  /* Initialize this backend's session state. */
1062 
1063  /* report this backend in the PgBackendStatus array */
1064  if (!bootstrap)
1065  pgstat_bestart();
1066 
1067  /* close the transaction we started above */
1068  if (!bootstrap)
1070 }
static void ClientCheckTimeoutHandler(void)
Definition: postinit.c:1241
int errhint(const char *fmt,...)
Definition: elog.c:1156
BackendId MyBackendId
Definition: globals.c:84
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
struct Port * MyProcPort
Definition: globals.c:46
CAC_state canAcceptConnections
Definition: libpq-be.h:138
void SharedInvalBackendInit(bool sendOnly)
Definition: sinvaladt.c:257
#define DEBUG3
Definition: elog.h:23
Oid GetUserId(void)
Definition: miscinit.c:495
FormData_pg_database * Form_pg_database
Definition: pg_database.h:81
PGPROC * MyProc
Definition: proc.c:68
static HeapTuple GetDatabaseTuple(const char *dbname)
Definition: postinit.c:96
ResourceOwner CurrentResourceOwner
Definition: resowner.c:146
void CommitTransactionCommand(void)
Definition: xact.c:2959
void ReleaseAuxProcessResources(bool isCommit)
Definition: resowner.c:908
void InitializeSession(void)
Definition: session.c:54
void ValidatePgVersion(const char *path)
Definition: miscinit.c:1547
void RelationCacheInitializePhase2(void)
Definition: relcache.c:3914
static void PerformAuthentication(Port *port)
Definition: postinit.c:185
static void LockTimeoutHandler(void)
Definition: postinit.c:1215
int errcode(int sqlerrcode)
Definition: elog.c:698
bool superuser(void)
Definition: superuser.c:46
void initialize_acl(void)
Definition: acl.c:4648
void pgstat_bestart(void)
bool RecoveryInProgress(void)
Definition: xlog.c:8341
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:250
#define OidIsValid(objectId)
Definition: c.h:710
Oid GetSessionUserId(void)
Definition: miscinit.c:529
bool HaveNFreeProcs(int n)
Definition: proc.c:676
static void CheckMyDatabase(const char *name, bool am_superuser, bool override_allow_connections)
Definition: postinit.c:305
bool IsBinaryUpgrade
Definition: globals.c:113
Oid MyDatabaseTableSpace
Definition: globals.c:90
bool IsBackgroundWorker
Definition: globals.c:114
void RelationCacheInitializePhase3(void)
Definition: relcache.c:3973
#define NAMEDATALEN
bool am_walsender
Definition: walsender.c:115
void pg_usleep(long microsec)
Definition: signal.c:53
int ReservedBackends
Definition: postmaster.c:217
#define FATAL
Definition: elog.h:49
void InitializeSearchPath(void)
Definition: namespace.c:4369
int MaxBackends
Definition: globals.c:139
bool IsUnderPostmaster
Definition: globals.c:112
#define RowExclusiveLock
Definition: lockdefs.h:38
int errdetail(const char *fmt,...)
Definition: elog.c:1042
int errcode_for_file_access(void)
Definition: elog.c:721
void pgstat_beinit(void)
static void IdleInTransactionSessionTimeoutHandler(void)
Definition: postinit.c:1225
void before_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:333
Oid databaseId
Definition: proc.h:154
static bool ThereIsAtLeastOneRole(void)
Definition: postinit.c:1252
void StartupXLOG(void)
Definition: xlog.c:6618
bool IsAutoVacuumWorkerProcess(void)
Definition: autovacuum.c:3410
const char * username
Definition: pgbench.c:282
void InvalidateCatalogSnapshot(void)
Definition: snapmgr.c:456
char * GetDatabasePath(Oid dbNode, Oid spcNode)
Definition: relpath.c:110
void SetDatabasePath(const char *path)
Definition: miscinit.c:308
#define WARNING
Definition: elog.h:40
void ShutdownXLOG(int code, Datum arg)
Definition: xlog.c:8762
static HeapTuple GetDatabaseTupleByOid(Oid dboid)
Definition: postinit.c:139
#define InvalidBackendId
Definition: backendid.h:23
bool am_db_walsender
Definition: walsender.c:118
Oid MyDatabaseId
Definition: globals.c:88
int PostAuthDelay
Definition: postgres.c:103
void LockSharedObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1018
void EnablePortalManager(void)
Definition: portalmem.c:104
static void ShutdownPostgres(int code, Datum arg)
Definition: postinit.c:1176
#define ereport(elevel,...)
Definition: elog.h:157
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
TimeoutId RegisterTimeout(TimeoutId id, timeout_handler_proc handler)
Definition: timeout.c:496
bool IsAutoVacuumLauncherProcess(void)
Definition: autovacuum.c:3404
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:804
void InitializeSessionUserIdStandalone(void)
Definition: miscinit.c:797
void StartTransactionCommand(void)
Definition: xact.c:2858
void CreateAuxProcessResourceOwner(void)
Definition: resowner.c:887
#define XACT_READ_COMMITTED
Definition: xact.h:37
static void IdleSessionTimeoutHandler(void)
Definition: postinit.c:1233
void InitializeSessionUserId(const char *rolename, Oid roleid)
Definition: miscinit.c:694
char * dbname
Definition: streamutil.c:51
static void process_startup_options(Port *port, bool am_superuser)
Definition: postinit.c:1077
int XactIsoLevel
Definition: xact.c:76
bool has_rolreplication(Oid roleid)
Definition: miscinit.c:676
void InitializeClientEncoding(void)
Definition: mbutils.c:281
void InitPlanCache(void)
Definition: plancache.c:127
void InitProcessPhase2(void)
Definition: proc.c:482
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:406
void RelationCacheInitialize(void)
Definition: relcache.c:3868
void ProcSignalInit(int pss_idx)
Definition: procsignal.c:161
void InitCatalogCache(void)
Definition: syscache.c:1044
static void StatementTimeoutHandler(void)
Definition: postinit.c:1193
void SetCurrentStatementStartTimestamp(void)
Definition: xact.c:834
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
#define NameStr(name)
Definition: c.h:681
static void process_settings(Oid databaseid, Oid roleid)
Definition: postinit.c:1142
void CheckDeadLockAlert(void)
Definition: proc.c:1871

◆ LockTimeoutHandler()

static void LockTimeoutHandler ( void  )
static

Definition at line 1215 of file postinit.c.

References kill, and MyProcPid.

Referenced by InitPostgres().

1216 {
1217 #ifdef HAVE_SETSID
1218  /* try to signal whole process group */
1219  kill(-MyProcPid, SIGINT);
1220 #endif
1221  kill(MyProcPid, SIGINT);
1222 }
int MyProcPid
Definition: globals.c:43
#define kill(pid, sig)
Definition: win32_port.h:464

◆ PerformAuthentication()

static void PerformAuthentication ( Port port)
static

Definition at line 185 of file postinit.c.

References _, ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, am_walsender, appendStringInfo(), Port::application_name, 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, Port::database_name, disable_timeout(), enable_timeout_after(), ereport, errmsg(), errmsg_internal(), FATAL, Port::gss, initStringInfo(), load_hba(), load_ident(), LOG, Log_connections, pfree(), PostmasterContext, set_ps_display(), Port::ssl_in_use, STATEMENT_TIMEOUT, TopMemoryContext, and Port::user_name.

Referenced by InitPostgres().

186 {
187  /* This should be set already, but let's make sure */
188  ClientAuthInProgress = true; /* limit visibility of log messages */
189 
190  /*
191  * In EXEC_BACKEND case, we didn't inherit the contents of pg_hba.conf
192  * etcetera from the postmaster, and have to load them ourselves.
193  *
194  * FIXME: [fork/exec] Ugh. Is there a way around this overhead?
195  */
196 #ifdef EXEC_BACKEND
197 
198  /*
199  * load_hba() and load_ident() want to work within the PostmasterContext,
200  * so create that if it doesn't exist (which it won't). We'll delete it
201  * again later, in PostgresMain.
202  */
203  if (PostmasterContext == NULL)
205  "Postmaster",
207 
208  if (!load_hba())
209  {
210  /*
211  * It makes no sense to continue if we fail to load the HBA file,
212  * since there is no way to connect to the database in this case.
213  */
214  ereport(FATAL,
215  (errmsg("could not load pg_hba.conf")));
216  }
217 
218  if (!load_ident())
219  {
220  /*
221  * It is ok to continue if we fail to load the IDENT file, although it
222  * means that you cannot log in using any of the authentication
223  * methods that need a user name mapping. load_ident() already logged
224  * the details of error to the log.
225  */
226  }
227 #endif
228 
229  /*
230  * Set up a timeout in case a buggy or malicious client fails to respond
231  * during authentication. Since we're inside a transaction and might do
232  * database access, we have to use the statement_timeout infrastructure.
233  */
235 
236  /*
237  * Now perform authentication exchange.
238  */
239  set_ps_display("authentication");
240  ClientAuthentication(port); /* might not return, if failure */
241 
242  /*
243  * Done with authentication. Disable the timeout, and log if needed.
244  */
246 
247  if (Log_connections)
248  {
249  StringInfoData logmsg;
250 
251  initStringInfo(&logmsg);
252  if (am_walsender)
253  appendStringInfo(&logmsg, _("replication connection authorized: user=%s"),
254  port->user_name);
255  else
256  appendStringInfo(&logmsg, _("connection authorized: user=%s"),
257  port->user_name);
258  if (!am_walsender)
259  appendStringInfo(&logmsg, _(" database=%s"), port->database_name);
260 
261  if (port->application_name != NULL)
262  appendStringInfo(&logmsg, _(" application_name=%s"),
263  port->application_name);
264 
265 #ifdef USE_SSL
266  if (port->ssl_in_use)
267  appendStringInfo(&logmsg, _(" SSL enabled (protocol=%s, cipher=%s, bits=%d)"),
268  be_tls_get_version(port),
269  be_tls_get_cipher(port),
270  be_tls_get_cipher_bits(port));
271 #endif
272 #ifdef ENABLE_GSS
273  if (port->gss)
274  {
275  const char *princ = be_gssapi_get_princ(port);
276 
277  if (princ)
278  appendStringInfo(&logmsg,
279  _(" GSS (authenticated=%s, encrypted=%s, principal=%s)"),
280  be_gssapi_get_auth(port) ? _("yes") : _("no"),
281  be_gssapi_get_enc(port) ? _("yes") : _("no"),
282  princ);
283  else
284  appendStringInfo(&logmsg,
285  _(" GSS (authenticated=%s, encrypted=%s)"),
286  be_gssapi_get_auth(port) ? _("yes") : _("no"),
287  be_gssapi_get_enc(port) ? _("yes") : _("no"));
288  }
289 #endif
290 
291  ereport(LOG, errmsg_internal("%s", logmsg.data));
292  pfree(logmsg.data);
293  }
294 
295  set_ps_display("startup");
296 
297  ClientAuthInProgress = false; /* client_min_messages is active now */
298 }
#define AllocSetContextCreate
Definition: memutils.h:173
const char * be_gssapi_get_princ(Port *port)
void ClientAuthentication(Port *port)
Definition: auth.c:383
bool ssl_in_use
Definition: libpq-be.h:209
#define LOG
Definition: elog.h:26
bool Log_connections
Definition: postmaster.c:240
bool load_ident(void)
Definition: hba.c:3029
int AuthenticationTimeout
Definition: postmaster.c:237
void set_ps_display(const char *activity)
Definition: ps_status.c:349
bool ClientAuthInProgress
Definition: postmaster.c:364
bool am_walsender
Definition: walsender.c:115
void pfree(void *pointer)
Definition: mcxt.c:1169
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define FATAL
Definition: elog.h:49
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:195
bool load_hba(void)
Definition: hba.c:2235
char * user_name
Definition: libpq-be.h:146
MemoryContext TopMemoryContext
Definition: mcxt.c:48
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
bool be_gssapi_get_enc(Port *port)
int be_tls_get_cipher_bits(Port *port)
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg_internal(const char *fmt,...)
Definition: elog.c:996
void enable_timeout_after(TimeoutId id, int delay_ms)
Definition: timeout.c:551
char * application_name
Definition: libpq-be.h:155
const char * be_tls_get_version(Port *port)
void * gss
Definition: libpq-be.h:203
int errmsg(const char *fmt,...)
Definition: elog.c:909
const char * be_tls_get_cipher(Port *port)
void disable_timeout(TimeoutId id, bool keep_indicator)
Definition: timeout.c:676
char * database_name
Definition: libpq-be.h:145
#define _(x)
Definition: elog.c:89
MemoryContext PostmasterContext
Definition: mcxt.c:50
bool be_gssapi_get_auth(Port *port)

◆ pg_split_opts()

void pg_split_opts ( char **  argv,
int *  argcp,
const char *  optstr 
)

Definition at line 430 of file postinit.c.

References appendStringInfoChar(), StringInfoData::data, initStringInfo(), pfree(), pstrdup(), and resetStringInfo().

Referenced by process_startup_options().

431 {
432  StringInfoData s;
433 
434  initStringInfo(&s);
435 
436  while (*optstr)
437  {
438  bool last_was_escape = false;
439 
440  resetStringInfo(&s);
441 
442  /* skip over leading space */
443  while (isspace((unsigned char) *optstr))
444  optstr++;
445 
446  if (*optstr == '\0')
447  break;
448 
449  /*
450  * Parse a single option, stopping at the first space, unless it's
451  * escaped.
452  */
453  while (*optstr)
454  {
455  if (isspace((unsigned char) *optstr) && !last_was_escape)
456  break;
457 
458  if (!last_was_escape && *optstr == '\\')
459  last_was_escape = true;
460  else
461  {
462  last_was_escape = false;
463  appendStringInfoChar(&s, *optstr);
464  }
465 
466  optstr++;
467  }
468 
469  /* now store the option in the next argv[] position */
470  argv[(*argcp)++] = pstrdup(s.data);
471  }
472 
473  pfree(s.data);
474 }
char * pstrdup(const char *in)
Definition: mcxt.c:1299
void pfree(void *pointer)
Definition: mcxt.c:1169
void resetStringInfo(StringInfo str)
Definition: stringinfo.c:75
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59

◆ process_settings()

static void process_settings ( Oid  databaseid,
Oid  roleid 
)
static

Definition at line 1142 of file postinit.c.

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().

1143 {
1144  Relation relsetting;
1145  Snapshot snapshot;
1146 
1147  if (!IsUnderPostmaster)
1148  return;
1149 
1150  relsetting = table_open(DbRoleSettingRelationId, AccessShareLock);
1151 
1152  /* read all the settings under the same snapshot for efficiency */
1153  snapshot = RegisterSnapshot(GetCatalogSnapshot(DbRoleSettingRelationId));
1154 
1155  /* Later settings are ignored if set earlier. */
1156  ApplySetting(snapshot, databaseid, roleid, relsetting, PGC_S_DATABASE_USER);
1157  ApplySetting(snapshot, InvalidOid, roleid, relsetting, PGC_S_USER);
1158  ApplySetting(snapshot, databaseid, InvalidOid, relsetting, PGC_S_DATABASE);
1159  ApplySetting(snapshot, InvalidOid, InvalidOid, relsetting, PGC_S_GLOBAL);
1160 
1161  UnregisterSnapshot(snapshot);
1162  table_close(relsetting, AccessShareLock);
1163 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
Snapshot RegisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:825
Snapshot GetCatalogSnapshot(Oid relid)
Definition: snapmgr.c:386
#define AccessShareLock
Definition: lockdefs.h:36
bool IsUnderPostmaster
Definition: globals.c:112
void UnregisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:867
#define InvalidOid
Definition: postgres_ext.h:36
void ApplySetting(Snapshot snapshot, Oid databaseid, Oid roleid, Relation relsetting, GucSource source)
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

◆ process_startup_options()

static void process_startup_options ( Port port,
bool  am_superuser 
)
static

Definition at line 1077 of file postinit.c.

References Assert, av, Port::cmdline_options, Port::guc_options, lfirst, list_head(), lnext(), name, palloc(), pg_split_opts(), PGC_BACKEND, PGC_S_CLIENT, PGC_SU_BACKEND, process_postgres_switches(), SetConfigOption(), and value.

Referenced by InitPostgres().

1078 {
1079  GucContext gucctx;
1080  ListCell *gucopts;
1081 
1082  gucctx = am_superuser ? PGC_SU_BACKEND : PGC_BACKEND;
1083 
1084  /*
1085  * First process any command-line switches that were included in the
1086  * startup packet, if we are in a regular backend.
1087  */
1088  if (port->cmdline_options != NULL)
1089  {
1090  /*
1091  * The maximum possible number of commandline arguments that could
1092  * come from port->cmdline_options is (strlen + 1) / 2; see
1093  * pg_split_opts().
1094  */
1095  char **av;
1096  int maxac;
1097  int ac;
1098 
1099  maxac = 2 + (strlen(port->cmdline_options) + 1) / 2;
1100 
1101  av = (char **) palloc(maxac * sizeof(char *));
1102  ac = 0;
1103 
1104  av[ac++] = "postgres";
1105 
1106  pg_split_opts(av, &ac, port->cmdline_options);
1107 
1108  av[ac] = NULL;
1109 
1110  Assert(ac < maxac);
1111 
1112  (void) process_postgres_switches(ac, av, gucctx, NULL);
1113  }
1114 
1115  /*
1116  * Process any additional GUC variable settings passed in startup packet.
1117  * These are handled exactly like command-line variables.
1118  */
1119  gucopts = list_head(port->guc_options);
1120  while (gucopts)
1121  {
1122  char *name;
1123  char *value;
1124 
1125  name = lfirst(gucopts);
1126  gucopts = lnext(port->guc_options, gucopts);
1127 
1128  value = lfirst(gucopts);
1129  gucopts = lnext(port->guc_options, gucopts);
1130 
1131  SetConfigOption(name, value, gucctx, PGC_S_CLIENT);
1132  }
1133 }
GucContext
Definition: guc.h:68
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:322
struct @11::@12 av[32]
List * guc_options
Definition: libpq-be.h:148
void SetConfigOption(const char *name, const char *value, GucContext context, GucSource source)
Definition: guc.c:8123
void pg_split_opts(char **argv, int *argcp, const char *optstr)
Definition: postinit.c:430
static ListCell * list_head(const List *l)
Definition: pg_list.h:125
static struct @143 value
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
const char * name
Definition: encode.c:561
void * palloc(Size size)
Definition: mcxt.c:1062
char * cmdline_options
Definition: libpq-be.h:147
void process_postgres_switches(int argc, char *argv[], GucContext ctx, const char **dbname)
Definition: postgres.c:3675

◆ ShutdownPostgres()

static void ShutdownPostgres ( int  code,
Datum  arg 
)
static

Definition at line 1176 of file postinit.c.

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

Referenced by InitPostgres().

1177 {
1178  /* Make sure we've killed any active transaction */
1180 
1181  /*
1182  * User locks are not released by transaction end, so be sure to release
1183  * them explicitly.
1184  */
1186 }
void AbortOutOfAnyTransaction(void)
Definition: xact.c:4599
#define USER_LOCKMETHOD
Definition: lock.h:131
void LockReleaseAll(LOCKMETHODID lockmethodid, bool allLocks)
Definition: lock.c:2180

◆ StatementTimeoutHandler()

static void StatementTimeoutHandler ( void  )
static

Definition at line 1193 of file postinit.c.

References ClientAuthInProgress, kill, MyProcPid, and sig.

Referenced by InitPostgres().

1194 {
1195  int sig = SIGINT;
1196 
1197  /*
1198  * During authentication the timeout is used to deal with
1199  * authentication_timeout - we want to quit in response to such timeouts.
1200  */
1202  sig = SIGTERM;
1203 
1204 #ifdef HAVE_SETSID
1205  /* try to signal whole process group */
1206  kill(-MyProcPid, sig);
1207 #endif
1208  kill(MyProcPid, sig);
1209 }
int MyProcPid
Definition: globals.c:43
#define kill(pid, sig)
Definition: win32_port.h:464
bool ClientAuthInProgress
Definition: postmaster.c:364
static int sig
Definition: pg_ctl.c:84

◆ ThereIsAtLeastOneRole()

static bool ThereIsAtLeastOneRole ( void  )
static

Definition at line 1252 of file postinit.c.

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

Referenced by InitPostgres().

1253 {
1254  Relation pg_authid_rel;
1255  TableScanDesc scan;
1256  bool result;
1257 
1258  pg_authid_rel = table_open(AuthIdRelationId, AccessShareLock);
1259 
1260  scan = table_beginscan_catalog(pg_authid_rel, 0, NULL);
1261  result = (heap_getnext(scan, ForwardScanDirection) != NULL);
1262 
1263  table_endscan(scan);
1264  table_close(pg_authid_rel, AccessShareLock);
1265 
1266  return result;
1267 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
TableScanDesc table_beginscan_catalog(Relation relation, int nkeys, struct ScanKeyData *key)
Definition: tableam.c:112
#define AccessShareLock
Definition: lockdefs.h:36
HeapTuple heap_getnext(TableScanDesc sscan, ScanDirection direction)
Definition: heapam.c:1340
static void table_endscan(TableScanDesc scan)
Definition: tableam.h:991
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39