mirror of
https://github.com/postgres/postgres.git
synced 2025-08-15 00:05:08 -04:00
Compare commits
No commits in common. "87027cb55bf7b33416880f7f5f5e67f4202d5881" and "ddd5f4f54a026db6a6692876d0d44aef902ab686" have entirely different histories.
87027cb55b
...
ddd5f4f54a
@ -23735,11 +23735,6 @@ SELECT * FROM pg_ls_dir('.') WITH ORDINALITY AS t(ls,n);
|
|||||||
<xref linkend="guc-log-destination"/>.
|
<xref linkend="guc-log-destination"/>.
|
||||||
The result reflects the contents of
|
The result reflects the contents of
|
||||||
the <filename>current_logfiles</filename> file.
|
the <filename>current_logfiles</filename> file.
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
This function is restricted to superusers and roles with privileges of
|
|
||||||
the <literal>pg_monitor</literal> role by default, but other users can
|
|
||||||
be granted EXECUTE to run the function.
|
|
||||||
</para></entry>
|
</para></entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
|
@ -1220,6 +1220,72 @@ gen_random_uuid() returns uuid
|
|||||||
ciphertexts of a given size.
|
ciphertexts of a given size.
|
||||||
</para>
|
</para>
|
||||||
</sect3>
|
</sect3>
|
||||||
|
|
||||||
|
<sect3 id="pgcrypto-notes-useful-reading">
|
||||||
|
<title>Useful Reading</title>
|
||||||
|
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para><ulink url="https://www.gnupg.org/gph/en/manual.html"></ulink></para>
|
||||||
|
<para>The GNU Privacy Handbook.</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para><ulink url="https://www.openwall.com/crypt/"></ulink></para>
|
||||||
|
<para>Describes the crypt-blowfish algorithm.</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<ulink url="https://www.iusmentis.com/security/passphrasefaq/"></ulink>
|
||||||
|
</para>
|
||||||
|
<para>How to choose a good password.</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para><ulink url="http://world.std.com/~reinhold/diceware.html"></ulink></para>
|
||||||
|
<para>Interesting idea for picking passwords.</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<ulink url="http://www.interhack.net/people/cmcurtin/snake-oil-faq.html"></ulink>
|
||||||
|
</para>
|
||||||
|
<para>Describes good and bad cryptography.</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</sect3>
|
||||||
|
|
||||||
|
<sect3 id="pgcrypto-notes-tech-ref">
|
||||||
|
<title>Technical References</title>
|
||||||
|
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para><ulink url="https://tools.ietf.org/html/rfc4880"></ulink></para>
|
||||||
|
<para>OpenPGP message format.</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para><ulink url="https://tools.ietf.org/html/rfc1321"></ulink></para>
|
||||||
|
<para>The MD5 Message-Digest Algorithm.</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para><ulink url="https://tools.ietf.org/html/rfc2104"></ulink></para>
|
||||||
|
<para>HMAC: Keyed-Hashing for Message Authentication.</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<ulink url="https://www.usenix.org/legacy/events/usenix99/provos.html"></ulink>
|
||||||
|
</para>
|
||||||
|
<para>Comparison of crypt-des, crypt-md5 and bcrypt algorithms.</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<ulink url="https://en.wikipedia.org/wiki/Fortuna_(PRNG)"></ulink>
|
||||||
|
</para>
|
||||||
|
<para>Description of Fortuna CSPRNG.</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para><ulink url="https://jlcooke.ca/random/"></ulink></para>
|
||||||
|
<para>Jean-Luc Cooke Fortuna-based <filename>/dev/random</filename> driver for Linux.</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</sect3>
|
||||||
</sect2>
|
</sect2>
|
||||||
|
|
||||||
<sect2 id="pgcrypto-author">
|
<sect2 id="pgcrypto-author">
|
||||||
|
@ -1007,10 +1007,18 @@ MemoryContextSwitchTo(MemoryContext context)
|
|||||||
static void
|
static void
|
||||||
handle_sighup(SIGNAL_ARGS)
|
handle_sighup(SIGNAL_ARGS)
|
||||||
{
|
{
|
||||||
|
int save_errno = errno;
|
||||||
|
|
||||||
got_SIGHUP = true;
|
got_SIGHUP = true;
|
||||||
SetLatch(MyLatch);
|
SetLatch(MyLatch);
|
||||||
|
|
||||||
|
errno = save_errno;
|
||||||
}
|
}
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
<varname>errno</varname> is saved and restored because
|
||||||
|
<function>SetLatch()</function> might change it. If that were not done
|
||||||
|
interrupted code that's currently inspecting <varname>errno</varname> might see the wrong
|
||||||
|
value.
|
||||||
</para>
|
</para>
|
||||||
</simplesect>
|
</simplesect>
|
||||||
|
|
||||||
|
@ -2447,17 +2447,11 @@ ExecGrant_Type_check(InternalGrant *istmt, HeapTuple tuple)
|
|||||||
|
|
||||||
pg_type_tuple = (Form_pg_type) GETSTRUCT(tuple);
|
pg_type_tuple = (Form_pg_type) GETSTRUCT(tuple);
|
||||||
|
|
||||||
/* Disallow GRANT on dependent types */
|
|
||||||
if (IsTrueArrayType(pg_type_tuple))
|
if (IsTrueArrayType(pg_type_tuple))
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_GRANT_OPERATION),
|
(errcode(ERRCODE_INVALID_GRANT_OPERATION),
|
||||||
errmsg("cannot set privileges of array types"),
|
errmsg("cannot set privileges of array types"),
|
||||||
errhint("Set the privileges of the element type instead.")));
|
errhint("Set the privileges of the element type instead.")));
|
||||||
if (pg_type_tuple->typtype == TYPTYPE_MULTIRANGE)
|
|
||||||
ereport(ERROR,
|
|
||||||
(errcode(ERRCODE_INVALID_GRANT_OPERATION),
|
|
||||||
errmsg("cannot set privileges of multirange types"),
|
|
||||||
errhint("Set the privileges of the range type instead.")));
|
|
||||||
|
|
||||||
/* Used GRANT DOMAIN on a non-domain? */
|
/* Used GRANT DOMAIN on a non-domain? */
|
||||||
if (istmt->objtype == OBJECT_DOMAIN &&
|
if (istmt->objtype == OBJECT_DOMAIN &&
|
||||||
@ -3812,35 +3806,6 @@ pg_type_aclmask_ext(Oid type_oid, Oid roleid, AclMode mask, AclMaskHow how,
|
|||||||
typeForm = (Form_pg_type) GETSTRUCT(tuple);
|
typeForm = (Form_pg_type) GETSTRUCT(tuple);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Likewise, multirange types don't manage their own permissions; consult
|
|
||||||
* the associated range type. (Note we must do this after the array step
|
|
||||||
* to get the right answer for arrays of multiranges.)
|
|
||||||
*/
|
|
||||||
if (typeForm->typtype == TYPTYPE_MULTIRANGE)
|
|
||||||
{
|
|
||||||
Oid rangetype = get_multirange_range(typeForm->oid);
|
|
||||||
|
|
||||||
ReleaseSysCache(tuple);
|
|
||||||
|
|
||||||
tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(rangetype));
|
|
||||||
if (!HeapTupleIsValid(tuple))
|
|
||||||
{
|
|
||||||
if (is_missing != NULL)
|
|
||||||
{
|
|
||||||
/* return "no privileges" instead of throwing an error */
|
|
||||||
*is_missing = true;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ereport(ERROR,
|
|
||||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
|
||||||
errmsg("type with OID %u does not exist",
|
|
||||||
rangetype)));
|
|
||||||
}
|
|
||||||
typeForm = (Form_pg_type) GETSTRUCT(tuple);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now get the type's owner and ACL from the tuple
|
* Now get the type's owner and ACL from the tuple
|
||||||
*/
|
*/
|
||||||
|
@ -326,15 +326,14 @@ TypeCreate(Oid newTypeOid,
|
|||||||
errmsg("fixed-size types must have storage PLAIN")));
|
errmsg("fixed-size types must have storage PLAIN")));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is a dependent type if it's an implicitly-created array type or
|
* This is a dependent type if it's an implicitly-created array type, or
|
||||||
* multirange type, or if it's a relation rowtype that's not a composite
|
* if it's a relation rowtype that's not a composite type. For such types
|
||||||
* type. For such types we'll leave the ACL empty, and we'll skip
|
* we'll leave the ACL empty, and we'll skip creating some dependency
|
||||||
* creating some dependency records because there will be a dependency
|
* records because there will be a dependency already through the
|
||||||
* already through the depended-on type or relation. (Caution: this is
|
* depended-on type or relation. (Caution: this is closely intertwined
|
||||||
* closely intertwined with some behavior in GenerateTypeDependencies.)
|
* with some behavior in GenerateTypeDependencies.)
|
||||||
*/
|
*/
|
||||||
isDependentType = isImplicitArray ||
|
isDependentType = isImplicitArray ||
|
||||||
typeType == TYPTYPE_MULTIRANGE ||
|
|
||||||
(OidIsValid(relationOid) && relationKind != RELKIND_COMPOSITE_TYPE);
|
(OidIsValid(relationOid) && relationKind != RELKIND_COMPOSITE_TYPE);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -535,9 +534,8 @@ TypeCreate(Oid newTypeOid,
|
|||||||
* relationKind and isImplicitArray are likewise somewhat expensive to deduce
|
* relationKind and isImplicitArray are likewise somewhat expensive to deduce
|
||||||
* from the tuple, so we make callers pass those (they're not optional).
|
* from the tuple, so we make callers pass those (they're not optional).
|
||||||
*
|
*
|
||||||
* isDependentType is true if this is an implicit array, multirange, or
|
* isDependentType is true if this is an implicit array or relation rowtype;
|
||||||
* relation rowtype; that means it doesn't need its own dependencies on owner
|
* that means it doesn't need its own dependencies on owner etc.
|
||||||
* etc.
|
|
||||||
*
|
*
|
||||||
* We make an extension-membership dependency if we're in an extension
|
* We make an extension-membership dependency if we're in an extension
|
||||||
* script and makeExtensionDep is true (and isDependentType isn't true).
|
* script and makeExtensionDep is true (and isDependentType isn't true).
|
||||||
@ -603,23 +601,18 @@ GenerateTypeDependencies(HeapTuple typeTuple,
|
|||||||
* Make dependencies on namespace, owner, ACL, extension.
|
* Make dependencies on namespace, owner, ACL, extension.
|
||||||
*
|
*
|
||||||
* Skip these for a dependent type, since it will have such dependencies
|
* Skip these for a dependent type, since it will have such dependencies
|
||||||
* indirectly through its depended-on type or relation. An exception is
|
* indirectly through its depended-on type or relation.
|
||||||
* that multiranges need their own namespace dependency, since we don't
|
|
||||||
* force them to be in the same schema as their range type.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* collects normal dependencies for bulk recording */
|
/* placeholder for all normal dependencies */
|
||||||
addrs_normal = new_object_addresses();
|
addrs_normal = new_object_addresses();
|
||||||
|
|
||||||
if (!isDependentType || typeForm->typtype == TYPTYPE_MULTIRANGE)
|
|
||||||
{
|
|
||||||
ObjectAddressSet(referenced, NamespaceRelationId,
|
|
||||||
typeForm->typnamespace);
|
|
||||||
add_exact_object_address(&referenced, addrs_normal);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isDependentType)
|
if (!isDependentType)
|
||||||
{
|
{
|
||||||
|
ObjectAddressSet(referenced, NamespaceRelationId,
|
||||||
|
typeForm->typnamespace);
|
||||||
|
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
|
||||||
|
|
||||||
recordDependencyOnOwner(TypeRelationId, typeObjectId,
|
recordDependencyOnOwner(TypeRelationId, typeObjectId,
|
||||||
typeForm->typowner);
|
typeForm->typowner);
|
||||||
|
|
||||||
@ -734,16 +727,6 @@ GenerateTypeDependencies(HeapTuple typeTuple,
|
|||||||
recordDependencyOn(&myself, &referenced,
|
recordDependencyOn(&myself, &referenced,
|
||||||
isImplicitArray ? DEPENDENCY_INTERNAL : DEPENDENCY_NORMAL);
|
isImplicitArray ? DEPENDENCY_INTERNAL : DEPENDENCY_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Note: you might expect that we should record an internal dependency of
|
|
||||||
* a multirange on its range type here, by analogy with the cases above.
|
|
||||||
* But instead, that is done by RangeCreate(), which also handles
|
|
||||||
* recording of other range-type-specific dependencies. That's pretty
|
|
||||||
* bogus. It's okay for now, because there are no cases where we need to
|
|
||||||
* regenerate the dependencies of a range or multirange type. But someday
|
|
||||||
* we might need to move that logic here to allow such regeneration.
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -777,10 +777,6 @@ GRANT EXECUTE ON FUNCTION pg_ls_logicalmapdir() TO pg_monitor;
|
|||||||
|
|
||||||
GRANT EXECUTE ON FUNCTION pg_ls_replslotdir(text) TO pg_monitor;
|
GRANT EXECUTE ON FUNCTION pg_ls_replslotdir(text) TO pg_monitor;
|
||||||
|
|
||||||
GRANT EXECUTE ON FUNCTION pg_current_logfile() TO pg_monitor;
|
|
||||||
|
|
||||||
GRANT EXECUTE ON FUNCTION pg_current_logfile(text) TO pg_monitor;
|
|
||||||
|
|
||||||
GRANT pg_read_all_settings TO pg_monitor;
|
GRANT pg_read_all_settings TO pg_monitor;
|
||||||
|
|
||||||
GRANT pg_read_all_stats TO pg_monitor;
|
GRANT pg_read_all_stats TO pg_monitor;
|
||||||
|
@ -3647,8 +3647,6 @@ RenameType(RenameStmt *stmt)
|
|||||||
errhint("You can alter type %s, which will alter the array type as well.",
|
errhint("You can alter type %s, which will alter the array type as well.",
|
||||||
format_type_be(typTup->typelem))));
|
format_type_be(typTup->typelem))));
|
||||||
|
|
||||||
/* we do allow separate renaming of multirange types, though */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If type is composite we need to rename associated pg_class entry too.
|
* If type is composite we need to rename associated pg_class entry too.
|
||||||
* RenameRelationInternal will call RenameTypeInternal automatically.
|
* RenameRelationInternal will call RenameTypeInternal automatically.
|
||||||
@ -3732,21 +3730,6 @@ AlterTypeOwner(List *names, Oid newOwnerId, ObjectType objecttype)
|
|||||||
errhint("You can alter type %s, which will alter the array type as well.",
|
errhint("You can alter type %s, which will alter the array type as well.",
|
||||||
format_type_be(typTup->typelem))));
|
format_type_be(typTup->typelem))));
|
||||||
|
|
||||||
/* don't allow direct alteration of multirange types, either */
|
|
||||||
if (typTup->typtype == TYPTYPE_MULTIRANGE)
|
|
||||||
{
|
|
||||||
Oid rangetype = get_multirange_range(typeOid);
|
|
||||||
|
|
||||||
/* We don't expect get_multirange_range to fail, but cope if so */
|
|
||||||
ereport(ERROR,
|
|
||||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
|
||||||
errmsg("cannot alter multirange type %s",
|
|
||||||
format_type_be(typeOid)),
|
|
||||||
OidIsValid(rangetype) ?
|
|
||||||
errhint("You can alter type %s, which will alter the multirange type as well.",
|
|
||||||
format_type_be(rangetype)) : 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the new owner is the same as the existing owner, consider the
|
* If the new owner is the same as the existing owner, consider the
|
||||||
* command to have succeeded. This is for dump restoration purposes.
|
* command to have succeeded. This is for dump restoration purposes.
|
||||||
@ -3786,13 +3769,13 @@ AlterTypeOwner(List *names, Oid newOwnerId, ObjectType objecttype)
|
|||||||
/*
|
/*
|
||||||
* AlterTypeOwner_oid - change type owner unconditionally
|
* AlterTypeOwner_oid - change type owner unconditionally
|
||||||
*
|
*
|
||||||
* This function recurses to handle dependent types (arrays and multiranges).
|
* This function recurses to handle a pg_class entry, if necessary. It
|
||||||
* It invokes any necessary access object hooks. If hasDependEntry is true,
|
* invokes any necessary access object hooks. If hasDependEntry is true, this
|
||||||
* this function modifies the pg_shdepend entry appropriately (this should be
|
* function modifies the pg_shdepend entry appropriately (this should be
|
||||||
* passed as false only for table rowtypes and dependent types).
|
* passed as false only for table rowtypes and array types).
|
||||||
*
|
*
|
||||||
* This is used by ALTER TABLE/TYPE OWNER commands, as well as by REASSIGN
|
* This is used by ALTER TABLE/TYPE OWNER commands, as well as by REASSIGN
|
||||||
* OWNED BY. It assumes the caller has done all needed checks.
|
* OWNED BY. It assumes the caller has done all needed check.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
AlterTypeOwner_oid(Oid typeOid, Oid newOwnerId, bool hasDependEntry)
|
AlterTypeOwner_oid(Oid typeOid, Oid newOwnerId, bool hasDependEntry)
|
||||||
@ -3832,7 +3815,7 @@ AlterTypeOwner_oid(Oid typeOid, Oid newOwnerId, bool hasDependEntry)
|
|||||||
* AlterTypeOwnerInternal - bare-bones type owner change.
|
* AlterTypeOwnerInternal - bare-bones type owner change.
|
||||||
*
|
*
|
||||||
* This routine simply modifies the owner of a pg_type entry, and recurses
|
* This routine simply modifies the owner of a pg_type entry, and recurses
|
||||||
* to handle any dependent types.
|
* to handle a possible array type.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId)
|
AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId)
|
||||||
@ -3882,19 +3865,6 @@ AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId)
|
|||||||
if (OidIsValid(typTup->typarray))
|
if (OidIsValid(typTup->typarray))
|
||||||
AlterTypeOwnerInternal(typTup->typarray, newOwnerId);
|
AlterTypeOwnerInternal(typTup->typarray, newOwnerId);
|
||||||
|
|
||||||
/* If it is a range type, update the associated multirange too */
|
|
||||||
if (typTup->typtype == TYPTYPE_RANGE)
|
|
||||||
{
|
|
||||||
Oid multirange_typeid = get_range_multirange(typeOid);
|
|
||||||
|
|
||||||
if (!OidIsValid(multirange_typeid))
|
|
||||||
ereport(ERROR,
|
|
||||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
|
||||||
errmsg("could not find multirange type for data type %s",
|
|
||||||
format_type_be(typeOid))));
|
|
||||||
AlterTypeOwnerInternal(multirange_typeid, newOwnerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clean up */
|
/* Clean up */
|
||||||
table_close(rel, RowExclusiveLock);
|
table_close(rel, RowExclusiveLock);
|
||||||
}
|
}
|
||||||
|
@ -1237,10 +1237,6 @@ create_tidrangescan_path(PlannerInfo *root, RelOptInfo *rel,
|
|||||||
*
|
*
|
||||||
* Note that we must handle subpaths = NIL, representing a dummy access path.
|
* Note that we must handle subpaths = NIL, representing a dummy access path.
|
||||||
* Also, there are callers that pass root = NULL.
|
* Also, there are callers that pass root = NULL.
|
||||||
*
|
|
||||||
* 'rows', when passed as a non-negative number, will be used to overwrite the
|
|
||||||
* returned path's row estimate. Otherwise, the row estimate is calculated
|
|
||||||
* by totalling the row estimates from the 'subpaths' list.
|
|
||||||
*/
|
*/
|
||||||
AppendPath *
|
AppendPath *
|
||||||
create_append_path(PlannerInfo *root,
|
create_append_path(PlannerInfo *root,
|
||||||
|
@ -1410,8 +1410,12 @@ AutoVacWorkerFailed(void)
|
|||||||
static void
|
static void
|
||||||
avl_sigusr2_handler(SIGNAL_ARGS)
|
avl_sigusr2_handler(SIGNAL_ARGS)
|
||||||
{
|
{
|
||||||
|
int save_errno = errno;
|
||||||
|
|
||||||
got_SIGUSR2 = true;
|
got_SIGUSR2 = true;
|
||||||
SetLatch(MyLatch);
|
SetLatch(MyLatch);
|
||||||
|
|
||||||
|
errno = save_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -852,11 +852,15 @@ IsCheckpointOnSchedule(double progress)
|
|||||||
static void
|
static void
|
||||||
ReqCheckpointHandler(SIGNAL_ARGS)
|
ReqCheckpointHandler(SIGNAL_ARGS)
|
||||||
{
|
{
|
||||||
|
int save_errno = errno;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The signaling process should have set ckpt_flags nonzero, so all we
|
* The signaling process should have set ckpt_flags nonzero, so all we
|
||||||
* need do is ensure that our main loop gets kicked out of any wait.
|
* need do is ensure that our main loop gets kicked out of any wait.
|
||||||
*/
|
*/
|
||||||
SetLatch(MyLatch);
|
SetLatch(MyLatch);
|
||||||
|
|
||||||
|
errno = save_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -60,8 +60,12 @@ HandleMainLoopInterrupts(void)
|
|||||||
void
|
void
|
||||||
SignalHandlerForConfigReload(SIGNAL_ARGS)
|
SignalHandlerForConfigReload(SIGNAL_ARGS)
|
||||||
{
|
{
|
||||||
|
int save_errno = errno;
|
||||||
|
|
||||||
ConfigReloadPending = true;
|
ConfigReloadPending = true;
|
||||||
SetLatch(MyLatch);
|
SetLatch(MyLatch);
|
||||||
|
|
||||||
|
errno = save_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -104,6 +108,10 @@ SignalHandlerForCrashExit(SIGNAL_ARGS)
|
|||||||
void
|
void
|
||||||
SignalHandlerForShutdownRequest(SIGNAL_ARGS)
|
SignalHandlerForShutdownRequest(SIGNAL_ARGS)
|
||||||
{
|
{
|
||||||
|
int save_errno = errno;
|
||||||
|
|
||||||
ShutdownRequestPending = true;
|
ShutdownRequestPending = true;
|
||||||
SetLatch(MyLatch);
|
SetLatch(MyLatch);
|
||||||
|
|
||||||
|
errno = save_errno;
|
||||||
}
|
}
|
||||||
|
@ -283,9 +283,13 @@ PgArchWakeup(void)
|
|||||||
static void
|
static void
|
||||||
pgarch_waken_stop(SIGNAL_ARGS)
|
pgarch_waken_stop(SIGNAL_ARGS)
|
||||||
{
|
{
|
||||||
|
int save_errno = errno;
|
||||||
|
|
||||||
/* set flag to do a final cycle and shut down afterwards */
|
/* set flag to do a final cycle and shut down afterwards */
|
||||||
ready_to_stop = true;
|
ready_to_stop = true;
|
||||||
SetLatch(MyLatch);
|
SetLatch(MyLatch);
|
||||||
|
|
||||||
|
errno = save_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2612,8 +2612,12 @@ InitProcessGlobals(void)
|
|||||||
static void
|
static void
|
||||||
handle_pm_pmsignal_signal(SIGNAL_ARGS)
|
handle_pm_pmsignal_signal(SIGNAL_ARGS)
|
||||||
{
|
{
|
||||||
|
int save_errno = errno;
|
||||||
|
|
||||||
pending_pm_pmsignal = true;
|
pending_pm_pmsignal = true;
|
||||||
SetLatch(MyLatch);
|
SetLatch(MyLatch);
|
||||||
|
|
||||||
|
errno = save_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2622,8 +2626,12 @@ handle_pm_pmsignal_signal(SIGNAL_ARGS)
|
|||||||
static void
|
static void
|
||||||
handle_pm_reload_request_signal(SIGNAL_ARGS)
|
handle_pm_reload_request_signal(SIGNAL_ARGS)
|
||||||
{
|
{
|
||||||
|
int save_errno = errno;
|
||||||
|
|
||||||
pending_pm_reload_request = true;
|
pending_pm_reload_request = true;
|
||||||
SetLatch(MyLatch);
|
SetLatch(MyLatch);
|
||||||
|
|
||||||
|
errno = save_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2703,6 +2711,8 @@ process_pm_reload_request(void)
|
|||||||
static void
|
static void
|
||||||
handle_pm_shutdown_request_signal(SIGNAL_ARGS)
|
handle_pm_shutdown_request_signal(SIGNAL_ARGS)
|
||||||
{
|
{
|
||||||
|
int save_errno = errno;
|
||||||
|
|
||||||
switch (postgres_signal_arg)
|
switch (postgres_signal_arg)
|
||||||
{
|
{
|
||||||
case SIGTERM:
|
case SIGTERM:
|
||||||
@ -2719,6 +2729,8 @@ handle_pm_shutdown_request_signal(SIGNAL_ARGS)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
SetLatch(MyLatch);
|
SetLatch(MyLatch);
|
||||||
|
|
||||||
|
errno = save_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2878,8 +2890,12 @@ process_pm_shutdown_request(void)
|
|||||||
static void
|
static void
|
||||||
handle_pm_child_exit_signal(SIGNAL_ARGS)
|
handle_pm_child_exit_signal(SIGNAL_ARGS)
|
||||||
{
|
{
|
||||||
|
int save_errno = errno;
|
||||||
|
|
||||||
pending_pm_child_exit = true;
|
pending_pm_child_exit = true;
|
||||||
SetLatch(MyLatch);
|
SetLatch(MyLatch);
|
||||||
|
|
||||||
|
errno = save_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
*/
|
*/
|
||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "access/xlog.h"
|
#include "access/xlog.h"
|
||||||
#include "access/xlogrecovery.h"
|
#include "access/xlogrecovery.h"
|
||||||
#include "access/xlogutils.h"
|
#include "access/xlogutils.h"
|
||||||
@ -93,27 +95,52 @@ static void StartupProcExit(int code, Datum arg);
|
|||||||
static void
|
static void
|
||||||
StartupProcTriggerHandler(SIGNAL_ARGS)
|
StartupProcTriggerHandler(SIGNAL_ARGS)
|
||||||
{
|
{
|
||||||
|
int save_errno = errno;
|
||||||
|
|
||||||
promote_signaled = true;
|
promote_signaled = true;
|
||||||
WakeupRecovery();
|
WakeupRecovery();
|
||||||
|
|
||||||
|
errno = save_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SIGHUP: set flag to re-read config file at next convenient time */
|
/* SIGHUP: set flag to re-read config file at next convenient time */
|
||||||
static void
|
static void
|
||||||
StartupProcSigHupHandler(SIGNAL_ARGS)
|
StartupProcSigHupHandler(SIGNAL_ARGS)
|
||||||
{
|
{
|
||||||
|
int save_errno = errno;
|
||||||
|
|
||||||
got_SIGHUP = true;
|
got_SIGHUP = true;
|
||||||
WakeupRecovery();
|
WakeupRecovery();
|
||||||
|
|
||||||
|
errno = save_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SIGTERM: set flag to abort redo and exit */
|
/* SIGTERM: set flag to abort redo and exit */
|
||||||
static void
|
static void
|
||||||
StartupProcShutdownHandler(SIGNAL_ARGS)
|
StartupProcShutdownHandler(SIGNAL_ARGS)
|
||||||
{
|
{
|
||||||
|
int save_errno = errno;
|
||||||
|
|
||||||
if (in_restore_command)
|
if (in_restore_command)
|
||||||
proc_exit(1);
|
{
|
||||||
|
/*
|
||||||
|
* If we are in a child process (e.g., forked by system() in
|
||||||
|
* RestoreArchivedFile()), we don't want to call any exit callbacks.
|
||||||
|
* The parent will take care of that.
|
||||||
|
*/
|
||||||
|
if (MyProcPid == (int) getpid())
|
||||||
|
proc_exit(1);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
write_stderr_signal_safe("StartupProcShutdownHandler() called in child process\n");
|
||||||
|
_exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
shutdown_requested = true;
|
shutdown_requested = true;
|
||||||
WakeupRecovery();
|
WakeupRecovery();
|
||||||
|
|
||||||
|
errno = save_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1642,6 +1642,10 @@ RemoveLogrotateSignalFiles(void)
|
|||||||
static void
|
static void
|
||||||
sigUsr1Handler(SIGNAL_ARGS)
|
sigUsr1Handler(SIGNAL_ARGS)
|
||||||
{
|
{
|
||||||
|
int save_errno = errno;
|
||||||
|
|
||||||
rotation_requested = true;
|
rotation_requested = true;
|
||||||
SetLatch(MyLatch);
|
SetLatch(MyLatch);
|
||||||
|
|
||||||
|
errno = save_errno;
|
||||||
}
|
}
|
||||||
|
@ -3476,8 +3476,12 @@ HandleWalSndInitStopping(void)
|
|||||||
static void
|
static void
|
||||||
WalSndLastCycleHandler(SIGNAL_ARGS)
|
WalSndLastCycleHandler(SIGNAL_ARGS)
|
||||||
{
|
{
|
||||||
|
int save_errno = errno;
|
||||||
|
|
||||||
got_SIGUSR2 = true;
|
got_SIGUSR2 = true;
|
||||||
SetLatch(MyLatch);
|
SetLatch(MyLatch);
|
||||||
|
|
||||||
|
errno = save_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set up signal handlers */
|
/* Set up signal handlers */
|
||||||
|
@ -2243,8 +2243,12 @@ GetNumRegisteredWaitEvents(WaitEventSet *set)
|
|||||||
static void
|
static void
|
||||||
latch_sigurg_handler(SIGNAL_ARGS)
|
latch_sigurg_handler(SIGNAL_ARGS)
|
||||||
{
|
{
|
||||||
|
int save_errno = errno;
|
||||||
|
|
||||||
if (waiting)
|
if (waiting)
|
||||||
sendSelfPipeByte();
|
sendSelfPipeByte();
|
||||||
|
|
||||||
|
errno = save_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send one byte to the self-pipe, to wake up WaitLatch */
|
/* Send one byte to the self-pipe, to wake up WaitLatch */
|
||||||
|
@ -638,6 +638,8 @@ CheckProcSignal(ProcSignalReason reason)
|
|||||||
void
|
void
|
||||||
procsignal_sigusr1_handler(SIGNAL_ARGS)
|
procsignal_sigusr1_handler(SIGNAL_ARGS)
|
||||||
{
|
{
|
||||||
|
int save_errno = errno;
|
||||||
|
|
||||||
if (CheckProcSignal(PROCSIG_CATCHUP_INTERRUPT))
|
if (CheckProcSignal(PROCSIG_CATCHUP_INTERRUPT))
|
||||||
HandleCatchupInterrupt();
|
HandleCatchupInterrupt();
|
||||||
|
|
||||||
@ -681,4 +683,6 @@ procsignal_sigusr1_handler(SIGNAL_ARGS)
|
|||||||
HandleRecoveryConflictInterrupt(PROCSIG_RECOVERY_CONFLICT_BUFFERPIN);
|
HandleRecoveryConflictInterrupt(PROCSIG_RECOVERY_CONFLICT_BUFFERPIN);
|
||||||
|
|
||||||
SetLatch(MyLatch);
|
SetLatch(MyLatch);
|
||||||
|
|
||||||
|
errno = save_errno;
|
||||||
}
|
}
|
||||||
|
@ -2970,6 +2970,8 @@ quickdie(SIGNAL_ARGS)
|
|||||||
void
|
void
|
||||||
die(SIGNAL_ARGS)
|
die(SIGNAL_ARGS)
|
||||||
{
|
{
|
||||||
|
int save_errno = errno;
|
||||||
|
|
||||||
/* Don't joggle the elbow of proc_exit */
|
/* Don't joggle the elbow of proc_exit */
|
||||||
if (!proc_exit_inprogress)
|
if (!proc_exit_inprogress)
|
||||||
{
|
{
|
||||||
@ -2991,6 +2993,8 @@ die(SIGNAL_ARGS)
|
|||||||
*/
|
*/
|
||||||
if (DoingCommandRead && whereToSendOutput != DestRemote)
|
if (DoingCommandRead && whereToSendOutput != DestRemote)
|
||||||
ProcessInterrupts();
|
ProcessInterrupts();
|
||||||
|
|
||||||
|
errno = save_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3000,6 +3004,8 @@ die(SIGNAL_ARGS)
|
|||||||
void
|
void
|
||||||
StatementCancelHandler(SIGNAL_ARGS)
|
StatementCancelHandler(SIGNAL_ARGS)
|
||||||
{
|
{
|
||||||
|
int save_errno = errno;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Don't joggle the elbow of proc_exit
|
* Don't joggle the elbow of proc_exit
|
||||||
*/
|
*/
|
||||||
@ -3011,6 +3017,8 @@ StatementCancelHandler(SIGNAL_ARGS)
|
|||||||
|
|
||||||
/* If we're still here, waken anything waiting on the process latch */
|
/* If we're still here, waken anything waiting on the process latch */
|
||||||
SetLatch(MyLatch);
|
SetLatch(MyLatch);
|
||||||
|
|
||||||
|
errno = save_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* signal handler for floating point exception */
|
/* signal handler for floating point exception */
|
||||||
|
@ -3737,3 +3737,31 @@ write_stderr(const char *fmt,...)
|
|||||||
#endif
|
#endif
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write a message to STDERR using only async-signal-safe functions. This can
|
||||||
|
* be used to safely emit a message from a signal handler.
|
||||||
|
*
|
||||||
|
* TODO: It is likely possible to safely do a limited amount of string
|
||||||
|
* interpolation (e.g., %s and %d), but that is not presently supported.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
write_stderr_signal_safe(const char *str)
|
||||||
|
{
|
||||||
|
int nwritten = 0;
|
||||||
|
int ntotal = strlen(str);
|
||||||
|
|
||||||
|
while (nwritten < ntotal)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = write(STDERR_FILENO, str + nwritten, ntotal - nwritten);
|
||||||
|
|
||||||
|
/* Just give up on error. There isn't much else we can do. */
|
||||||
|
if (rc == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
nwritten += rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -363,6 +363,8 @@ schedule_alarm(TimestampTz now)
|
|||||||
static void
|
static void
|
||||||
handle_sig_alarm(SIGNAL_ARGS)
|
handle_sig_alarm(SIGNAL_ARGS)
|
||||||
{
|
{
|
||||||
|
int save_errno = errno;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Bump the holdoff counter, to make sure nothing we call will process
|
* Bump the holdoff counter, to make sure nothing we call will process
|
||||||
* interrupts directly. No timeout handler should do that, but these
|
* interrupts directly. No timeout handler should do that, but these
|
||||||
@ -450,6 +452,8 @@ handle_sig_alarm(SIGNAL_ARGS)
|
|||||||
}
|
}
|
||||||
|
|
||||||
RESUME_INTERRUPTS();
|
RESUME_INTERRUPTS();
|
||||||
|
|
||||||
|
errno = save_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1868,7 +1868,7 @@ selectDumpableType(TypeInfo *tyinfo, Archive *fout)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* skip auto-generated array and multirange types */
|
/* skip auto-generated array types */
|
||||||
if (tyinfo->isArray || tyinfo->isMultirange)
|
if (tyinfo->isArray || tyinfo->isMultirange)
|
||||||
{
|
{
|
||||||
tyinfo->dobj.objType = DO_DUMMY_TYPE;
|
tyinfo->dobj.objType = DO_DUMMY_TYPE;
|
||||||
@ -1876,8 +1876,8 @@ selectDumpableType(TypeInfo *tyinfo, Archive *fout)
|
|||||||
/*
|
/*
|
||||||
* Fall through to set the dump flag; we assume that the subsequent
|
* Fall through to set the dump flag; we assume that the subsequent
|
||||||
* rules will do the same thing as they would for the array's base
|
* rules will do the same thing as they would for the array's base
|
||||||
* type or multirange's range type. (We cannot reliably look up the
|
* type. (We cannot reliably look up the base type here, since
|
||||||
* base type here, since getTypes may not have processed it yet.)
|
* getTypes may not have processed it yet.)
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5770,7 +5770,7 @@ getTypes(Archive *fout, int *numTypes)
|
|||||||
else
|
else
|
||||||
tyinfo[i].isArray = false;
|
tyinfo[i].isArray = false;
|
||||||
|
|
||||||
if (tyinfo[i].typtype == TYPTYPE_MULTIRANGE)
|
if (tyinfo[i].typtype == 'm')
|
||||||
tyinfo[i].isMultirange = true;
|
tyinfo[i].isMultirange = true;
|
||||||
else
|
else
|
||||||
tyinfo[i].isMultirange = false;
|
tyinfo[i].isMultirange = false;
|
||||||
|
@ -152,6 +152,7 @@ ResetCancelConn(void)
|
|||||||
static void
|
static void
|
||||||
handle_sigint(SIGNAL_ARGS)
|
handle_sigint(SIGNAL_ARGS)
|
||||||
{
|
{
|
||||||
|
int save_errno = errno;
|
||||||
char errbuf[256];
|
char errbuf[256];
|
||||||
|
|
||||||
CancelRequested = true;
|
CancelRequested = true;
|
||||||
@ -172,6 +173,8 @@ handle_sigint(SIGNAL_ARGS)
|
|||||||
write_stderr(errbuf);
|
write_stderr(errbuf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
errno = save_errno; /* just in case the write changed it */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -57,6 +57,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* yyyymmddN */
|
/* yyyymmddN */
|
||||||
#define CATALOG_VERSION_NO 202402142
|
#define CATALOG_VERSION_NO 202402141
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -536,4 +536,10 @@ extern void write_jsonlog(ErrorData *edata);
|
|||||||
*/
|
*/
|
||||||
extern void write_stderr(const char *fmt,...) pg_attribute_printf(1, 2);
|
extern void write_stderr(const char *fmt,...) pg_attribute_printf(1, 2);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write a message to STDERR using only async-signal-safe functions. This can
|
||||||
|
* be used to safely emit a message from a signal handler.
|
||||||
|
*/
|
||||||
|
extern void write_stderr_signal_safe(const char *fmt);
|
||||||
|
|
||||||
#endif /* ELOG_H */
|
#endif /* ELOG_H */
|
||||||
|
@ -46,105 +46,23 @@
|
|||||||
#include "c.h"
|
#include "c.h"
|
||||||
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#ifndef FRONTEND
|
|
||||||
#include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef FRONTEND
|
#ifndef FRONTEND
|
||||||
#include "libpq/pqsignal.h"
|
#include "libpq/pqsignal.h"
|
||||||
#include "miscadmin.h"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef PG_SIGNAL_COUNT /* Windows */
|
|
||||||
#define PG_NSIG (PG_SIGNAL_COUNT)
|
|
||||||
#elif defined(NSIG)
|
|
||||||
#define PG_NSIG (NSIG)
|
|
||||||
#else
|
|
||||||
#define PG_NSIG (64) /* XXX: wild guess */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Check a couple of common signals to make sure PG_NSIG is accurate. */
|
|
||||||
StaticAssertDecl(SIGUSR2 < PG_NSIG, "SIGUSR2 >= PG_NSIG");
|
|
||||||
StaticAssertDecl(SIGHUP < PG_NSIG, "SIGHUP >= PG_NSIG");
|
|
||||||
StaticAssertDecl(SIGTERM < PG_NSIG, "SIGTERM >= PG_NSIG");
|
|
||||||
StaticAssertDecl(SIGALRM < PG_NSIG, "SIGALRM >= PG_NSIG");
|
|
||||||
|
|
||||||
static volatile pqsigfunc pqsignal_handlers[PG_NSIG];
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Except when called with SIG_IGN or SIG_DFL, pqsignal() sets up this function
|
|
||||||
* as the handler for all signals. This wrapper handler function checks that
|
|
||||||
* it is called within a process that the server knows about (i.e., any process
|
|
||||||
* that has called InitProcessGlobals(), such as a client backend), and not a
|
|
||||||
* child process forked by system(3), etc. This check ensures that such child
|
|
||||||
* processes do not modify shared memory, which is often detrimental. If the
|
|
||||||
* check succeeds, the function originally provided to pqsignal() is called.
|
|
||||||
* Otherwise, the default signal handler is installed and then called.
|
|
||||||
*
|
|
||||||
* This wrapper also handles restoring the value of errno.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
wrapper_handler(SIGNAL_ARGS)
|
|
||||||
{
|
|
||||||
int save_errno = errno;
|
|
||||||
|
|
||||||
#ifndef FRONTEND
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We expect processes to set MyProcPid before calling pqsignal() or
|
|
||||||
* before accepting signals.
|
|
||||||
*/
|
|
||||||
Assert(MyProcPid);
|
|
||||||
Assert(MyProcPid != PostmasterPid || !IsUnderPostmaster);
|
|
||||||
|
|
||||||
if (unlikely(MyProcPid != (int) getpid()))
|
|
||||||
{
|
|
||||||
pqsignal(postgres_signal_arg, SIG_DFL);
|
|
||||||
raise(postgres_signal_arg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
(*pqsignal_handlers[postgres_signal_arg]) (postgres_signal_arg);
|
|
||||||
|
|
||||||
errno = save_errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set up a signal handler, with SA_RESTART, for signal "signo"
|
* Set up a signal handler, with SA_RESTART, for signal "signo"
|
||||||
*
|
*
|
||||||
* Returns the previous handler.
|
* Returns the previous handler.
|
||||||
*
|
|
||||||
* NB: If called within a signal handler, race conditions may lead to bogus
|
|
||||||
* return values. You should either avoid calling this within signal handlers
|
|
||||||
* or ignore the return value.
|
|
||||||
*
|
|
||||||
* XXX: Since no in-tree callers use the return value, and there is little
|
|
||||||
* reason to do so, it would be nice if we could convert this to a void
|
|
||||||
* function instead of providing potentially-bogus return values.
|
|
||||||
* Unfortunately, that requires modifying the pqsignal() in legacy-pqsignal.c,
|
|
||||||
* which in turn requires an SONAME bump, which is probably not worth it.
|
|
||||||
*/
|
*/
|
||||||
pqsigfunc
|
pqsigfunc
|
||||||
pqsignal(int signo, pqsigfunc func)
|
pqsignal(int signo, pqsigfunc func)
|
||||||
{
|
{
|
||||||
pqsigfunc orig_func = pqsignal_handlers[signo]; /* assumed atomic */
|
|
||||||
#if !(defined(WIN32) && defined(FRONTEND))
|
#if !(defined(WIN32) && defined(FRONTEND))
|
||||||
struct sigaction act,
|
struct sigaction act,
|
||||||
oact;
|
oact;
|
||||||
#else
|
|
||||||
pqsigfunc ret;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Assert(signo < PG_NSIG);
|
|
||||||
|
|
||||||
if (func != SIG_IGN && func != SIG_DFL)
|
|
||||||
{
|
|
||||||
pqsignal_handlers[signo] = func; /* assumed atomic */
|
|
||||||
func = wrapper_handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !(defined(WIN32) && defined(FRONTEND))
|
|
||||||
act.sa_handler = func;
|
act.sa_handler = func;
|
||||||
sigemptyset(&act.sa_mask);
|
sigemptyset(&act.sa_mask);
|
||||||
act.sa_flags = SA_RESTART;
|
act.sa_flags = SA_RESTART;
|
||||||
@ -154,15 +72,9 @@ pqsignal(int signo, pqsigfunc func)
|
|||||||
#endif
|
#endif
|
||||||
if (sigaction(signo, &act, &oact) < 0)
|
if (sigaction(signo, &act, &oact) < 0)
|
||||||
return SIG_ERR;
|
return SIG_ERR;
|
||||||
else if (oact.sa_handler == wrapper_handler)
|
return oact.sa_handler;
|
||||||
return orig_func;
|
|
||||||
else
|
|
||||||
return oact.sa_handler;
|
|
||||||
#else
|
#else
|
||||||
/* Forward to Windows native signal system. */
|
/* Forward to Windows native signal system. */
|
||||||
if ((ret = signal(signo, func)) == wrapper_handler)
|
return signal(signo, func);
|
||||||
return orig_func;
|
|
||||||
else
|
|
||||||
return ret;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -171,7 +171,7 @@ $standby1->safe_psql('postgres', "SELECT pg_sync_replication_slots();");
|
|||||||
# flagged as 'synced'
|
# flagged as 'synced'
|
||||||
is( $standby1->safe_psql(
|
is( $standby1->safe_psql(
|
||||||
'postgres',
|
'postgres',
|
||||||
q{SELECT count(*) = 2 FROM pg_replication_slots WHERE slot_name IN ('lsub1_slot', 'lsub2_slot') AND synced AND NOT temporary;}
|
q{SELECT count(*) = 2 FROM pg_replication_slots WHERE slot_name IN ('lsub1_slot', 'lsub2_slot') AND synced;}
|
||||||
),
|
),
|
||||||
"t",
|
"t",
|
||||||
'logical slots have synced as true on standby');
|
'logical slots have synced as true on standby');
|
||||||
@ -227,13 +227,6 @@ $standby1->reload;
|
|||||||
$subscriber1->safe_psql('postgres',
|
$subscriber1->safe_psql('postgres',
|
||||||
"ALTER SUBSCRIPTION regress_mysub1 ENABLE");
|
"ALTER SUBSCRIPTION regress_mysub1 ENABLE");
|
||||||
|
|
||||||
# This wait ensures that confirmed_flush_lsn has been moved to latest
|
|
||||||
# position.
|
|
||||||
$primary->wait_for_catchup('regress_mysub1');
|
|
||||||
|
|
||||||
# To ensure that restart_lsn has moved to a recent WAL position, we need
|
|
||||||
# to log XLOG_RUNNING_XACTS and make sure the same is processed as well
|
|
||||||
$primary->psql('postgres', "CHECKPOINT");
|
|
||||||
$primary->wait_for_catchup('regress_mysub1');
|
$primary->wait_for_catchup('regress_mysub1');
|
||||||
|
|
||||||
# Do not allow any further advancement of the restart_lsn for the lsub1_slot.
|
# Do not allow any further advancement of the restart_lsn for the lsub1_slot.
|
||||||
@ -263,7 +256,7 @@ $standby1->wait_for_log(qr/dropped replication slot "lsub1_slot" of dbid [0-9]+/
|
|||||||
# flagged as 'synced'
|
# flagged as 'synced'
|
||||||
is( $standby1->safe_psql(
|
is( $standby1->safe_psql(
|
||||||
'postgres',
|
'postgres',
|
||||||
q{SELECT conflict_reason IS NULL AND synced AND NOT temporary FROM pg_replication_slots WHERE slot_name = 'lsub1_slot';}
|
q{SELECT conflict_reason IS NULL AND synced FROM pg_replication_slots WHERE slot_name = 'lsub1_slot';}
|
||||||
),
|
),
|
||||||
"t",
|
"t",
|
||||||
'logical slot is re-synced');
|
'logical slot is re-synced');
|
||||||
|
@ -144,6 +144,7 @@ owner of sequence deptest_a_seq
|
|||||||
owner of table deptest
|
owner of table deptest
|
||||||
owner of function deptest_func()
|
owner of function deptest_func()
|
||||||
owner of type deptest_enum
|
owner of type deptest_enum
|
||||||
|
owner of type deptest_multirange
|
||||||
owner of type deptest_range
|
owner of type deptest_range
|
||||||
owner of table deptest2
|
owner of table deptest2
|
||||||
owner of sequence ss1
|
owner of sequence ss1
|
||||||
|
@ -683,23 +683,3 @@ SELECT gist_stratnum_identity(18::smallint);
|
|||||||
18
|
18
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
-- pg_current_logfile
|
|
||||||
CREATE ROLE regress_current_logfile;
|
|
||||||
-- not available by default
|
|
||||||
SELECT has_function_privilege('regress_current_logfile',
|
|
||||||
'pg_current_logfile()', 'EXECUTE');
|
|
||||||
has_function_privilege
|
|
||||||
------------------------
|
|
||||||
f
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
GRANT pg_monitor TO regress_current_logfile;
|
|
||||||
-- role has privileges of pg_monitor and can execute the function
|
|
||||||
SELECT has_function_privilege('regress_current_logfile',
|
|
||||||
'pg_current_logfile()', 'EXECUTE');
|
|
||||||
has_function_privilege
|
|
||||||
------------------------
|
|
||||||
t
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
DROP ROLE regress_current_logfile;
|
|
||||||
|
@ -3115,36 +3115,6 @@ select _textrange1(textrange2('a','z')) @> 'b'::text;
|
|||||||
drop type textrange1;
|
drop type textrange1;
|
||||||
drop type textrange2;
|
drop type textrange2;
|
||||||
--
|
--
|
||||||
-- Multiranges don't have their own ownership or permissions.
|
|
||||||
--
|
|
||||||
create type textrange1 as range(subtype=text, multirange_type_name=multitextrange1, collation="C");
|
|
||||||
create role regress_multirange_owner;
|
|
||||||
alter type multitextrange1 owner to regress_multirange_owner; -- fail
|
|
||||||
ERROR: cannot alter multirange type multitextrange1
|
|
||||||
HINT: You can alter type textrange1, which will alter the multirange type as well.
|
|
||||||
alter type textrange1 owner to regress_multirange_owner;
|
|
||||||
set role regress_multirange_owner;
|
|
||||||
revoke usage on type multitextrange1 from public; -- fail
|
|
||||||
ERROR: cannot set privileges of multirange types
|
|
||||||
HINT: Set the privileges of the range type instead.
|
|
||||||
revoke usage on type textrange1 from public;
|
|
||||||
\dT+ *textrange1*
|
|
||||||
List of data types
|
|
||||||
Schema | Name | Internal name | Size | Elements | Owner | Access privileges | Description
|
|
||||||
--------+-----------------+-----------------+------+----------+--------------------------+-----------------------------------------------------+-------------
|
|
||||||
public | multitextrange1 | multitextrange1 | var | | regress_multirange_owner | |
|
|
||||||
public | textrange1 | textrange1 | var | | regress_multirange_owner | regress_multirange_owner=U/regress_multirange_owner |
|
|
||||||
(2 rows)
|
|
||||||
|
|
||||||
create temp table test1(f1 multitextrange1[]);
|
|
||||||
revoke usage on type textrange1 from regress_multirange_owner;
|
|
||||||
create temp table test2(f1 multitextrange1[]); -- fail
|
|
||||||
ERROR: permission denied for type multitextrange1
|
|
||||||
drop table test1;
|
|
||||||
drop type textrange1;
|
|
||||||
reset role;
|
|
||||||
drop role regress_multirange_owner;
|
|
||||||
--
|
|
||||||
-- Test polymorphic type system
|
-- Test polymorphic type system
|
||||||
--
|
--
|
||||||
create function anyarray_anymultirange_func(a anyarray, r anymultirange)
|
create function anyarray_anymultirange_func(a anyarray, r anymultirange)
|
||||||
|
@ -254,14 +254,3 @@ FROM pg_walfile_name_offset('0/0'::pg_lsn + :segment_size - 1),
|
|||||||
-- test stratnum support functions
|
-- test stratnum support functions
|
||||||
SELECT gist_stratnum_identity(3::smallint);
|
SELECT gist_stratnum_identity(3::smallint);
|
||||||
SELECT gist_stratnum_identity(18::smallint);
|
SELECT gist_stratnum_identity(18::smallint);
|
||||||
|
|
||||||
-- pg_current_logfile
|
|
||||||
CREATE ROLE regress_current_logfile;
|
|
||||||
-- not available by default
|
|
||||||
SELECT has_function_privilege('regress_current_logfile',
|
|
||||||
'pg_current_logfile()', 'EXECUTE');
|
|
||||||
GRANT pg_monitor TO regress_current_logfile;
|
|
||||||
-- role has privileges of pg_monitor and can execute the function
|
|
||||||
SELECT has_function_privilege('regress_current_logfile',
|
|
||||||
'pg_current_logfile()', 'EXECUTE');
|
|
||||||
DROP ROLE regress_current_logfile;
|
|
||||||
|
@ -700,27 +700,6 @@ select _textrange1(textrange2('a','z')) @> 'b'::text;
|
|||||||
drop type textrange1;
|
drop type textrange1;
|
||||||
drop type textrange2;
|
drop type textrange2;
|
||||||
|
|
||||||
--
|
|
||||||
-- Multiranges don't have their own ownership or permissions.
|
|
||||||
--
|
|
||||||
create type textrange1 as range(subtype=text, multirange_type_name=multitextrange1, collation="C");
|
|
||||||
create role regress_multirange_owner;
|
|
||||||
|
|
||||||
alter type multitextrange1 owner to regress_multirange_owner; -- fail
|
|
||||||
alter type textrange1 owner to regress_multirange_owner;
|
|
||||||
set role regress_multirange_owner;
|
|
||||||
revoke usage on type multitextrange1 from public; -- fail
|
|
||||||
revoke usage on type textrange1 from public;
|
|
||||||
\dT+ *textrange1*
|
|
||||||
create temp table test1(f1 multitextrange1[]);
|
|
||||||
revoke usage on type textrange1 from regress_multirange_owner;
|
|
||||||
create temp table test2(f1 multitextrange1[]); -- fail
|
|
||||||
|
|
||||||
drop table test1;
|
|
||||||
drop type textrange1;
|
|
||||||
reset role;
|
|
||||||
drop role regress_multirange_owner;
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Test polymorphic type system
|
-- Test polymorphic type system
|
||||||
--
|
--
|
||||||
|
Loading…
x
Reference in New Issue
Block a user