/* *Initializethebasicenvironmentforapostmasterchild * *Shouldbecalledasearlyaspossibleafterthechild'sstartup.However, *onEXEC_BACKENDbuildsitdoesneedtobeafterread_backend_variables().
*/ void
InitPostmasterChild(void)
{
IsUnderPostmaster = true; /* we are a postmaster subprocess now */
/* Request a signal if the postmaster dies, if possible. */
PostmasterDeathSignalInit();
/* Don't give the pipe to subprograms that we execute. */ #ifndef WIN32 if (fcntl(postmaster_alive_fds[POSTMASTER_FD_WATCH], F_SETFD, FD_CLOEXEC) < 0)
ereport(FATAL,
(errcode_for_socket_access(),
errmsg_internal("could not set postmaster death monitoring pipe to FD_CLOEXEC mode: %m"))); #endif
}
/* Compute paths, no postmaster to inherit from */ if (my_exec_path[0] == '\0')
{ if (find_my_exec(argv0, my_exec_path) < 0)
elog(FATAL, "%s: could not locate my own executable path",
argv0);
}
if (pkglib_path[0] == '\0')
get_pkglib_path(my_exec_path, pkglib_path);
}
void
SetDatabasePath(constchar *path)
{ /* This should happen only once per process */
Assert(!DatabasePath);
DatabasePath = MemoryContextStrdup(TopMemoryContext, path);
}
if (stat(DataDir, &stat_buf) != 0)
{ if (errno == ENOENT)
ereport(FATAL,
(errcode_for_file_access(),
errmsg("data directory \"%s\" does not exist",
DataDir))); else
ereport(FATAL,
(errcode_for_file_access(),
errmsg("could not read permissions of directory \"%s\": %m",
DataDir)));
}
/* eventual chdir would fail anyway, but let's test ... */ if (!S_ISDIR(stat_buf.st_mode))
ereport(FATAL,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("specified data directory \"%s\" is not a directory",
DataDir)));
/* *Checkthatthedirectorybelongstomyuserid;ifnot,reject. * *Thischeckisanessentialpartoftheinterlockthatpreventstwo *postmastersfromstartinginthesamedirectory(seeCreateLockFile()). *Donotremoveorweakenit. * *XXXcanwesafelyenablethischeckonWindows?
*/ #if !defined(WIN32) && !defined(__CYGWIN__) if (stat_buf.st_uid != geteuid())
ereport(FATAL,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("data directory \"%s\" has wrong ownership",
DataDir),
errhint("The server must be started by the user that owns the data directory."))); #endif
/* *Checkifthedirectoryhascorrectpermissions.Ifnot,reject. * *Onlytwopossiblemodesareallowed,0700and0750.Thelattermode *indicatesthatgroupread/executeshouldbeallowedonallnewly *createdfilesanddirectories. * *XXXtemporarilysuppresscheckwhenonWindows,becausetheremaynot *bepropersupportforUnix-yfilepermissions.Needtothinkofa *reasonablechecktoapplyonWindows.
*/ #if !defined(WIN32) && !defined(__CYGWIN__) if (stat_buf.st_mode & PG_MODE_MASK_GROUP)
ereport(FATAL,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("data directory \"%s\" has invalid permissions",
DataDir),
errdetail("Permissions should be u=rwx (0700) or u=rwx,g=rx (0750)."))); #endif
/* We force the effective user ID to match, too */
CurrentUserId = userid;
/* Also update the is_superuser GUC to match OuterUserId's property */
SetConfigOption("is_superuser",
is_superuser ? "on" : "off",
PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
}
/* *GetSessionUserId/SetSessionUserId-get/setthesessionuserID.
*/
Oid
GetSessionUserId(void)
{
Assert(OidIsValid(SessionUserId)); return SessionUserId;
}
/* call only once */
Assert(!OidIsValid(AuthenticatedUserId));
AuthenticatedUserId = userid;
/* Also mark our PGPROC entry with the authenticated user id */ /* (We assume this is an atomic store so no lock is needed) */
MyProc->roleId = userid;
}
void
SetUserIdAndContext(Oid userid, bool sec_def_context)
{ /* We throw the same error SET ROLE would. */ if (InSecurityRestrictedOperation())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("cannot set parameter \"%s\" within security-restricted operation", "role")));
CurrentUserId = userid; if (sec_def_context)
SecurityRestrictionContext |= SECURITY_LOCAL_USERID_CHANGE; else
SecurityRestrictionContext &= ~SECURITY_LOCAL_USERID_CHANGE;
}
/* *Lookuptherole,eitherbynameifthat'sgivenorbyOIDifnot.
*/ if (rolename != NULL)
{
roleTup = SearchSysCache1(AUTHNAME, PointerGetDatum(rolename)); if (!HeapTupleIsValid(roleTup))
ereport(FATAL,
(errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
errmsg("role \"%s\" does not exist", rolename)));
} else
{
roleTup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid)); if (!HeapTupleIsValid(roleTup))
ereport(FATAL,
(errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
errmsg("role with OID %u does not exist", roleid)));
}
/* Copy authn_id into the space after the struct */ if (serialized.authn_id_len >= 0)
{
Assert(maxsize >= (serialized.authn_id_len + 1));
memcpy(start_address,
MyClientConnectionInfo.authn_id, /* include the NULL terminator to ease deserialization */
serialized.authn_id_len + 1);
}
}
/* *Readthefiletogettheoldowner'sPID.Noteracecondition *here:filemighthavebeendeletedsincewetriedtocreateit.
*/
fd = open(filename, O_RDONLY, pg_file_create_mode); if (fd < 0)
{ if (errno == ENOENT) continue; /* race condition; try again */
ereport(FATAL,
(errcode_for_file_access(),
errmsg("could not open lock file \"%s\": %m",
filename)));
}
pgstat_report_wait_start(WAIT_EVENT_LOCK_FILE_CREATE_READ); if ((len = read(fd, buffer, sizeof(buffer) - 1)) < 0)
ereport(FATAL,
(errcode_for_file_access(),
errmsg("could not read lock file \"%s\": %m",
filename)));
pgstat_report_wait_end();
close(fd);
if (len == 0)
{
ereport(FATAL,
(errcode(ERRCODE_LOCK_FILE_EXISTS),
errmsg("lock file \"%s\" is empty", filename),
errhint("Either another server is starting, or the lock file is the remnant of a previous server startup crash.")));
}
buffer[len] = '\0';
encoded_pid = atoi(buffer);
/* if pid < 0, the pid is for postgres, not postmaster */
other_pid = (pid_t) (encoded_pid < 0 ? -encoded_pid : encoded_pid);
if (other_pid <= 0)
elog(FATAL, "bogus data in lock file \"%s\": \"%s\"",
filename, buffer);
/* *Checktoseeiftheotherprocessstillexists * *Perdiscussionabove,my_pid,my_p_pid,andmy_gp_pidcanbe *ignoredasfalsematches. * *Normallykill()willfailwithESRCHifthegivenPIDdoesn't *exist. * *WecantreattheEPERM-errorcaseasokaybecausethaterror *impliesthattheexistingprocesshasadifferentuseridthanwe *do,whichmeansitcannotbeacompetingpostmaster.Apostmaster *cannotsuccessfullyattachtoadatadirectoryownedbyauserid *otherthanitsown,asenforcedincheckDataDir().Also,sincewe *createthelockfilesmode0600/0640,we'dhavefailedaboveifthe *lockfilebelongedtoanotheruserid---whichmeansthatwhatever *processkill()isreportingaboutisn'ttheonethatmadethe *lockfile.(NOTE:thislastconsiderationistheonlyonethat *keepsusfromblowingawayaUnixsocketfilebelongingtoan *instanceofPostgresbeingrunbysomeoneelse,atleaston *machineswhere/tmphasn'tgotastickybit.)
*/ if (other_pid != my_pid && other_pid != my_p_pid &&
other_pid != my_gp_pid)
{ if (kill(other_pid, 0) == 0 ||
(errno != ESRCH && errno != EPERM))
{ /* lockfile belongs to a live process */
ereport(FATAL,
(errcode(ERRCODE_LOCK_FILE_EXISTS),
errmsg("lock file \"%s\" already exists",
filename),
isDDLock ?
(encoded_pid < 0 ?
errhint("Is another postgres (PID %d) running in data directory \"%s\"?",
(int) other_pid, refName) :
errhint("Is another postmaster (PID %d) running in data directory \"%s\"?",
(int) other_pid, refName)) :
(encoded_pid < 0 ?
errhint("Is another postgres (PID %d) using socket file \"%s\"?",
(int) other_pid, refName) :
errhint("Is another postmaster (PID %d) using socket file \"%s\"?",
(int) other_pid, refName))));
}
}
for (lineno = 1; lineno < LOCK_FILE_LINE_SHMEM_KEY; lineno++)
{ if ((ptr = strchr(ptr, '\n')) == NULL) break;
ptr++;
}
if (ptr != NULL &&
sscanf(ptr, "%lu %lu", &id1, &id2) == 2)
{ if (PGSharedMemoryIsInUse(id1, id2))
ereport(FATAL,
(errcode(ERRCODE_LOCK_FILE_EXISTS),
errmsg("pre-existing shared memory block (key %lu, ID %lu) is still in use",
id1, id2),
errhint("Terminate any old server processes associated with data directory \"%s\".",
refName)));
}
}
/* *Lookslikenobody'shome.Unlinkthefileandtryagaintocreate *it.Needaloopbecauseofpossibleraceconditionagainstother *would-becreators.
*/ if (unlink(filename) < 0)
ereport(FATAL,
(errcode_for_file_access(),
errmsg("could not remove old lock file \"%s\": %m",
filename),
errhint("The file seems accidentally left over, but " "it could not be removed. Please remove the file " "by hand and try again.")));
}
errno = 0;
pgstat_report_wait_start(WAIT_EVENT_LOCK_FILE_CREATE_WRITE); if (write(fd, buffer, strlen(buffer)) != strlen(buffer))
{ int save_errno = errno;
close(fd);
unlink(filename); /* if write didn't set errno, assume problem is no disk space */
errno = save_errno ? save_errno : ENOSPC;
ereport(FATAL,
(errcode_for_file_access(),
errmsg("could not write lock file \"%s\": %m", filename)));
}
pgstat_report_wait_end();
pgstat_report_wait_start(WAIT_EVENT_LOCK_FILE_CREATE_SYNC); if (pg_fsync(fd) != 0)
{ int save_errno = errno;
close(fd);
unlink(filename);
errno = save_errno;
ereport(FATAL,
(errcode_for_file_access(),
errmsg("could not write lock file \"%s\": %m", filename)));
}
pgstat_report_wait_end(); if (close(fd) != 0)
{ int save_errno = errno;
/* *Andrewritethedata.Sincewewriteinasinglekernelcall,this *updateshouldappearatomictoonlookers.
*/
len = strlen(destbuffer);
errno = 0;
pgstat_report_wait_start(WAIT_EVENT_LOCK_FILE_ADDTODATADIR_WRITE); if (pg_pwrite(fd, destbuffer, len, 0) != len)
{
pgstat_report_wait_end(); /* if write didn't set errno, assume problem is no disk space */ if (errno == 0)
errno = ENOSPC;
ereport(LOG,
(errcode_for_file_access(),
errmsg("could not write to file \"%s\": %m",
DIRECTORY_LOCK_FILE)));
close(fd); return;
}
pgstat_report_wait_end();
pgstat_report_wait_start(WAIT_EVENT_LOCK_FILE_ADDTODATADIR_SYNC); if (pg_fsync(fd) != 0)
{
ereport(LOG,
(errcode_for_file_access(),
errmsg("could not write to file \"%s\": %m",
DIRECTORY_LOCK_FILE)));
}
pgstat_report_wait_end(); if (close(fd) != 0)
{
ereport(LOG,
(errcode_for_file_access(),
errmsg("could not write to file \"%s\": %m",
DIRECTORY_LOCK_FILE)));
}
}
/* *Recheckthatthedatadirectorylockfilestillexistswithexpected *content.ReturntrueifthelockfileappearsOK,falseifitisn't. * *Wecallthisperiodicallyinthepostmaster.Theideaisthatifthe *lockfilehasbeenremovedorreplacedbyanotherpostmaster,weshould *doapanicdatabaseshutdown.Therefore,weshouldreturntrueifthere *isanydoubt:wedonotwanttocauseapanicshutdownunnecessarily. *TransientfailureslikeEINTRorENFILEshouldnotcauseustofail. *(Iftherereallyissomethingwrong,we'lldetectitonafuturerecheck.)
*/ bool
RecheckDataDirLockFile(void)
{ int fd; int len; long file_pid; char buffer[BLCKSZ];
fd = open(DIRECTORY_LOCK_FILE, O_RDWR | PG_BINARY, 0); if (fd < 0)
{ /* *Therearemanyforeseeablefalse-positiveerrorconditions.For *safety,failonlyonenumeratedclearly-something-is-wrong *conditions.
*/ switch (errno)
{ case ENOENT: case ENOTDIR: /* disaster */
ereport(LOG,
(errcode_for_file_access(),
errmsg("could not open file \"%s\": %m",
DIRECTORY_LOCK_FILE))); returnfalse; default: /* non-fatal, at least for now */
ereport(LOG,
(errcode_for_file_access(),
errmsg("could not open file \"%s\": %m; continuing anyway",
DIRECTORY_LOCK_FILE))); returntrue;
}
}
pgstat_report_wait_start(WAIT_EVENT_LOCK_FILE_RECHECKDATADIR_READ);
len = read(fd, buffer, sizeof(buffer) - 1);
pgstat_report_wait_end(); if (len < 0)
{
ereport(LOG,
(errcode_for_file_access(),
errmsg("could not read from file \"%s\": %m",
DIRECTORY_LOCK_FILE)));
close(fd); returntrue; /* treat read failure as nonfatal */
}
buffer[len] = '\0';
close(fd);
file_pid = atol(buffer); if (file_pid == getpid()) returntrue; /* all is well */
file = AllocateFile(full_path, "r"); if (!file)
{ if (errno == ENOENT)
ereport(FATAL,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("\"%s\" is not a valid data directory",
path),
errdetail("File \"%s\" is missing.", full_path))); else
ereport(FATAL,
(errcode_for_file_access(),
errmsg("could not open file \"%s\": %m", full_path)));
}
if (ret != 1 || endptr == file_version_string)
ereport(FATAL,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("\"%s\" is not a valid data directory",
path),
errdetail("File \"%s\" does not contain valid data.",
full_path),
errhint("You might need to initdb.")));
FreeFile(file);
if (my_major != file_major)
ereport(FATAL,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("database files are incompatible with server"),
errdetail("The data directory was initialized by PostgreSQL version %s, " "which is not compatible with this version %s.",
file_version_string, my_version_string)));
}
/* Flag telling that we are loading shared_preload_libraries */ bool process_shared_preload_libraries_in_progress = false; bool process_shared_preload_libraries_done = false;
if (libraries == NULL || libraries[0] == '\0') return; /* nothing to do */
/* Need a modifiable copy of string */
rawstring = pstrdup(libraries);
/* Parse string into list of filename paths */ if (!SplitDirectoriesString(rawstring, ',', &elemlist))
{ /* syntax error in list */
list_free_deep(elemlist);
pfree(rawstring);
ereport(LOG,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("invalid list syntax in parameter \"%s\"",
gucname))); return;
}
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.51Bemerkung:
(vorverarbeitet am 2026-08-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.