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 InitCommunication (void)
 
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 537 of file postinit.c.

References DebugFileOpen(), InitBufferPoolAccess(), InitCommunication(), InitFileAccess(), InitSync(), and smgrinit().

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

538 {
539  /*
540  * Attach to shared memory and semaphores, and initialize our
541  * input/output/debugging file descriptors.
542  */
544  DebugFileOpen();
545 
546  /* Do local initialization of file, storage and buffer managers */
547  InitFileAccess();
548  InitSync();
549  smgrinit();
551 }
static void InitCommunication(void)
Definition: postinit.c:429
void InitBufferPoolAccess(void)
Definition: bufmgr.c:2592
void DebugFileOpen(void)
Definition: elog.c:1922
void smgrinit(void)
Definition: smgr.c:111
void InitSync(void)
Definition: sync.c:128
void InitFileAccess(void)
Definition: fd.c:873

◆ CheckMyDatabase()

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

Definition at line 306 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().

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

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

Referenced by InitPostgres().

1253 {
1255  InterruptPending = true;
1256  SetLatch(MyLatch);
1257 }
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 97 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().

98 {
99  HeapTuple tuple;
100  Relation relation;
101  SysScanDesc scan;
102  ScanKeyData key[1];
103 
104  /*
105  * form a scan key
106  */
107  ScanKeyInit(&key[0],
108  Anum_pg_database_datname,
109  BTEqualStrategyNumber, F_NAMEEQ,
111 
112  /*
113  * Open pg_database and fetch a tuple. Force heap scan if we haven't yet
114  * built the critical shared relcache entries (i.e., we're starting up
115  * without a shared relcache cache file).
116  */
117  relation = table_open(DatabaseRelationId, AccessShareLock);
118  scan = systable_beginscan(relation, DatabaseNameIndexId,
120  NULL,
121  1, key);
122 
123  tuple = systable_getnext(scan);
124 
125  /* Must copy tuple before releasing buffer */
126  if (HeapTupleIsValid(tuple))
127  tuple = heap_copytuple(tuple);
128 
129  /* all done */
130  systable_endscan(scan);
131  table_close(relation, AccessShareLock);
132 
133  return tuple;
134 }
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 140 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().

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

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

Referenced by InitPostgres().

1237 {
1239  InterruptPending = true;
1240  SetLatch(MyLatch);
1241 }
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 1244 of file postinit.c.

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

Referenced by InitPostgres().

1245 {
1247  InterruptPending = true;
1248  SetLatch(MyLatch);
1249 }
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

◆ InitCommunication()

static void InitCommunication ( void  )
static

Definition at line 429 of file postinit.c.

References CreateSharedMemoryAndSemaphores(), and IsUnderPostmaster.

Referenced by BaseInit().

430 {
431  /*
432  * initialize shared memory and semaphores appropriately.
433  */
434  if (!IsUnderPostmaster) /* postmaster already did this */
435  {
436  /*
437  * We're running a postgres bootstrap process or a standalone backend,
438  * so we need to set up shmem.
439  */
441  }
442 }
bool IsUnderPostmaster
Definition: globals.c:112
void CreateSharedMemoryAndSemaphores(void)
Definition: ipci.c:95

◆ InitializeMaxBackends()

void InitializeMaxBackends ( void  )

Definition at line 515 of file postinit.c.

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

Referenced by AuxiliaryProcessMain(), PostgresMain(), and PostmasterMain().

516 {
517  Assert(MaxBackends == 0);
518 
519  /* the extra unit accounts for the autovacuum launcher */
522 
523  /* internal error because the values were all checked previously */
525  elog(ERROR, "too many backends configured");
526 }
#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:116
#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 579 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(), InitBufferPoolBackend(), 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, on_shmem_exit(), PerformAuthentication(), pg_usleep(), pgstat_beinit(), pgstat_bestart(), pgstat_initialize(), 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().

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

◆ LockTimeoutHandler()

static void LockTimeoutHandler ( void  )
static

Definition at line 1226 of file postinit.c.

References kill, and MyProcPid.

Referenced by InitPostgres().

1227 {
1228 #ifdef HAVE_SETSID
1229  /* try to signal whole process group */
1230  kill(-MyProcPid, SIGINT);
1231 #endif
1232  kill(MyProcPid, SIGINT);
1233 }
int MyProcPid
Definition: globals.c:43
#define kill(pid, sig)
Definition: win32_port.h:454

◆ PerformAuthentication()

static void PerformAuthentication ( Port port)
static

Definition at line 186 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().

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

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

Referenced by process_startup_options().

457 {
458  StringInfoData s;
459 
460  initStringInfo(&s);
461 
462  while (*optstr)
463  {
464  bool last_was_escape = false;
465 
466  resetStringInfo(&s);
467 
468  /* skip over leading space */
469  while (isspace((unsigned char) *optstr))
470  optstr++;
471 
472  if (*optstr == '\0')
473  break;
474 
475  /*
476  * Parse a single option, stopping at the first space, unless it's
477  * escaped.
478  */
479  while (*optstr)
480  {
481  if (isspace((unsigned char) *optstr) && !last_was_escape)
482  break;
483 
484  if (!last_was_escape && *optstr == '\\')
485  last_was_escape = true;
486  else
487  {
488  last_was_escape = false;
489  appendStringInfoChar(&s, *optstr);
490  }
491 
492  optstr++;
493  }
494 
495  /* now store the option in the next argv[] position */
496  argv[(*argcp)++] = pstrdup(s.data);
497  }
498 
499  pfree(s.data);
500 }
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 1153 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().

1154 {
1155  Relation relsetting;
1156  Snapshot snapshot;
1157 
1158  if (!IsUnderPostmaster)
1159  return;
1160 
1161  relsetting = table_open(DbRoleSettingRelationId, AccessShareLock);
1162 
1163  /* read all the settings under the same snapshot for efficiency */
1164  snapshot = RegisterSnapshot(GetCatalogSnapshot(DbRoleSettingRelationId));
1165 
1166  /* Later settings are ignored if set earlier. */
1167  ApplySetting(snapshot, databaseid, roleid, relsetting, PGC_S_DATABASE_USER);
1168  ApplySetting(snapshot, InvalidOid, roleid, relsetting, PGC_S_USER);
1169  ApplySetting(snapshot, databaseid, InvalidOid, relsetting, PGC_S_DATABASE);
1170  ApplySetting(snapshot, InvalidOid, InvalidOid, relsetting, PGC_S_GLOBAL);
1171 
1172  UnregisterSnapshot(snapshot);
1173  table_close(relsetting, AccessShareLock);
1174 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
Snapshot RegisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:810
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:852
#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 1088 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().

1089 {
1090  GucContext gucctx;
1091  ListCell *gucopts;
1092 
1093  gucctx = am_superuser ? PGC_SU_BACKEND : PGC_BACKEND;
1094 
1095  /*
1096  * First process any command-line switches that were included in the
1097  * startup packet, if we are in a regular backend.
1098  */
1099  if (port->cmdline_options != NULL)
1100  {
1101  /*
1102  * The maximum possible number of commandline arguments that could
1103  * come from port->cmdline_options is (strlen + 1) / 2; see
1104  * pg_split_opts().
1105  */
1106  char **av;
1107  int maxac;
1108  int ac;
1109 
1110  maxac = 2 + (strlen(port->cmdline_options) + 1) / 2;
1111 
1112  av = (char **) palloc(maxac * sizeof(char *));
1113  ac = 0;
1114 
1115  av[ac++] = "postgres";
1116 
1117  pg_split_opts(av, &ac, port->cmdline_options);
1118 
1119  av[ac] = NULL;
1120 
1121  Assert(ac < maxac);
1122 
1123  (void) process_postgres_switches(ac, av, gucctx, NULL);
1124  }
1125 
1126  /*
1127  * Process any additional GUC variable settings passed in startup packet.
1128  * These are handled exactly like command-line variables.
1129  */
1130  gucopts = list_head(port->guc_options);
1131  while (gucopts)
1132  {
1133  char *name;
1134  char *value;
1135 
1136  name = lfirst(gucopts);
1137  gucopts = lnext(port->guc_options, gucopts);
1138 
1139  value = lfirst(gucopts);
1140  gucopts = lnext(port->guc_options, gucopts);
1141 
1142  SetConfigOption(name, value, gucctx, PGC_S_CLIENT);
1143  }
1144 }
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:8086
void pg_split_opts(char **argv, int *argcp, const char *optstr)
Definition: postinit.c:456
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:515
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 1187 of file postinit.c.

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

Referenced by InitPostgres().

1188 {
1189  /* Make sure we've killed any active transaction */
1191 
1192  /*
1193  * User locks are not released by transaction end, so be sure to release
1194  * them explicitly.
1195  */
1197 }
void AbortOutOfAnyTransaction(void)
Definition: xact.c:4579
#define USER_LOCKMETHOD
Definition: lock.h:130
void LockReleaseAll(LOCKMETHODID lockmethodid, bool allLocks)
Definition: lock.c:2180

◆ StatementTimeoutHandler()

static void StatementTimeoutHandler ( void  )
static

Definition at line 1204 of file postinit.c.

References ClientAuthInProgress, kill, MyProcPid, and sig.

Referenced by InitPostgres().

1205 {
1206  int sig = SIGINT;
1207 
1208  /*
1209  * During authentication the timeout is used to deal with
1210  * authentication_timeout - we want to quit in response to such timeouts.
1211  */
1213  sig = SIGTERM;
1214 
1215 #ifdef HAVE_SETSID
1216  /* try to signal whole process group */
1217  kill(-MyProcPid, sig);
1218 #endif
1219  kill(MyProcPid, sig);
1220 }
int MyProcPid
Definition: globals.c:43
#define kill(pid, sig)
Definition: win32_port.h:454
bool ClientAuthInProgress
Definition: postmaster.c:364
static int sig
Definition: pg_ctl.c:84

◆ ThereIsAtLeastOneRole()

static bool ThereIsAtLeastOneRole ( void  )
static

Definition at line 1263 of file postinit.c.

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

Referenced by InitPostgres().

1264 {
1265  Relation pg_authid_rel;
1266  TableScanDesc scan;
1267  bool result;
1268 
1269  pg_authid_rel = table_open(AuthIdRelationId, AccessShareLock);
1270 
1271  scan = table_beginscan_catalog(pg_authid_rel, 0, NULL);
1272  result = (heap_getnext(scan, ForwardScanDirection) != NULL);
1273 
1274  table_endscan(scan);
1275  table_close(pg_authid_rel, AccessShareLock);
1276 
1277  return result;
1278 }
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