Compare commits

..

No commits in common. "87027cb55bf7b33416880f7f5f5e67f4202d5881" and "ddd5f4f54a026db6a6692876d0d44aef902ab686" have entirely different histories.

32 changed files with 233 additions and 302 deletions

View File

@ -23735,11 +23735,6 @@ SELECT * FROM pg_ls_dir('.') WITH ORDINALITY AS t(ls,n);
<xref linkend="guc-log-destination"/>.
The result reflects the contents of
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>
</row>

View File

@ -1220,6 +1220,72 @@ gen_random_uuid() returns uuid
ciphertexts of a given size.
</para>
</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 id="pgcrypto-author">

View File

@ -1007,10 +1007,18 @@ MemoryContextSwitchTo(MemoryContext context)
static void
handle_sighup(SIGNAL_ARGS)
{
int save_errno = errno;
got_SIGHUP = true;
SetLatch(MyLatch);
errno = save_errno;
}
</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>
</simplesect>

View File

@ -2447,17 +2447,11 @@ ExecGrant_Type_check(InternalGrant *istmt, HeapTuple tuple)
pg_type_tuple = (Form_pg_type) GETSTRUCT(tuple);
/* Disallow GRANT on dependent types */
if (IsTrueArrayType(pg_type_tuple))
ereport(ERROR,
(errcode(ERRCODE_INVALID_GRANT_OPERATION),
errmsg("cannot set privileges of array types"),
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? */
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);
}
/*
* 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
*/

View File

@ -326,15 +326,14 @@ TypeCreate(Oid newTypeOid,
errmsg("fixed-size types must have storage PLAIN")));
/*
* 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
* type. For such types we'll leave the ACL empty, and we'll skip
* creating some dependency records because there will be a dependency
* already through the depended-on type or relation. (Caution: this is
* closely intertwined with some behavior in GenerateTypeDependencies.)
* This is a dependent type if it's an implicitly-created array type, or
* if it's a relation rowtype that's not a composite type. For such types
* we'll leave the ACL empty, and we'll skip creating some dependency
* records because there will be a dependency already through the
* depended-on type or relation. (Caution: this is closely intertwined
* with some behavior in GenerateTypeDependencies.)
*/
isDependentType = isImplicitArray ||
typeType == TYPTYPE_MULTIRANGE ||
(OidIsValid(relationOid) && relationKind != RELKIND_COMPOSITE_TYPE);
/*
@ -535,9 +534,8 @@ TypeCreate(Oid newTypeOid,
* relationKind and isImplicitArray are likewise somewhat expensive to deduce
* from the tuple, so we make callers pass those (they're not optional).
*
* isDependentType is true if this is an implicit array, multirange, or
* relation rowtype; that means it doesn't need its own dependencies on owner
* etc.
* isDependentType is true if this is an implicit array or relation rowtype;
* that means it doesn't need its own dependencies on owner etc.
*
* We make an extension-membership dependency if we're in an extension
* script and makeExtensionDep is true (and isDependentType isn't true).
@ -603,23 +601,18 @@ GenerateTypeDependencies(HeapTuple typeTuple,
* Make dependencies on namespace, owner, ACL, extension.
*
* Skip these for a dependent type, since it will have such dependencies
* indirectly through its depended-on type or relation. An exception is
* that multiranges need their own namespace dependency, since we don't
* force them to be in the same schema as their range type.
* indirectly through its depended-on type or relation.
*/
/* collects normal dependencies for bulk recording */
/* placeholder for all normal dependencies */
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)
{
ObjectAddressSet(referenced, NamespaceRelationId,
typeForm->typnamespace);
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
recordDependencyOnOwner(TypeRelationId, typeObjectId,
typeForm->typowner);
@ -734,16 +727,6 @@ GenerateTypeDependencies(HeapTuple typeTuple,
recordDependencyOn(&myself, &referenced,
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.
*/
}
/*

View File

@ -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_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_stats TO pg_monitor;

View File

@ -3647,8 +3647,6 @@ RenameType(RenameStmt *stmt)
errhint("You can alter type %s, which will alter the array type as well.",
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.
* 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.",
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
* 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
*
* This function recurses to handle dependent types (arrays and multiranges).
* It invokes any necessary access object hooks. If hasDependEntry is true,
* this function modifies the pg_shdepend entry appropriately (this should be
* passed as false only for table rowtypes and dependent types).
* This function recurses to handle a pg_class entry, if necessary. It
* invokes any necessary access object hooks. If hasDependEntry is true, this
* function modifies the pg_shdepend entry appropriately (this should be
* passed as false only for table rowtypes and array types).
*
* 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
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.
*
* 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
AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId)
@ -3882,19 +3865,6 @@ AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId)
if (OidIsValid(typTup->typarray))
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 */
table_close(rel, RowExclusiveLock);
}

View File

@ -1237,10 +1237,6 @@ create_tidrangescan_path(PlannerInfo *root, RelOptInfo *rel,
*
* Note that we must handle subpaths = NIL, representing a dummy access path.
* 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 *
create_append_path(PlannerInfo *root,

View File

@ -1410,8 +1410,12 @@ AutoVacWorkerFailed(void)
static void
avl_sigusr2_handler(SIGNAL_ARGS)
{
int save_errno = errno;
got_SIGUSR2 = true;
SetLatch(MyLatch);
errno = save_errno;
}

View File

@ -852,11 +852,15 @@ IsCheckpointOnSchedule(double progress)
static void
ReqCheckpointHandler(SIGNAL_ARGS)
{
int save_errno = errno;
/*
* 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.
*/
SetLatch(MyLatch);
errno = save_errno;
}

View File

@ -60,8 +60,12 @@ HandleMainLoopInterrupts(void)
void
SignalHandlerForConfigReload(SIGNAL_ARGS)
{
int save_errno = errno;
ConfigReloadPending = true;
SetLatch(MyLatch);
errno = save_errno;
}
/*
@ -104,6 +108,10 @@ SignalHandlerForCrashExit(SIGNAL_ARGS)
void
SignalHandlerForShutdownRequest(SIGNAL_ARGS)
{
int save_errno = errno;
ShutdownRequestPending = true;
SetLatch(MyLatch);
errno = save_errno;
}

View File

@ -283,9 +283,13 @@ PgArchWakeup(void)
static void
pgarch_waken_stop(SIGNAL_ARGS)
{
int save_errno = errno;
/* set flag to do a final cycle and shut down afterwards */
ready_to_stop = true;
SetLatch(MyLatch);
errno = save_errno;
}
/*

View File

@ -2612,8 +2612,12 @@ InitProcessGlobals(void)
static void
handle_pm_pmsignal_signal(SIGNAL_ARGS)
{
int save_errno = errno;
pending_pm_pmsignal = true;
SetLatch(MyLatch);
errno = save_errno;
}
/*
@ -2622,8 +2626,12 @@ handle_pm_pmsignal_signal(SIGNAL_ARGS)
static void
handle_pm_reload_request_signal(SIGNAL_ARGS)
{
int save_errno = errno;
pending_pm_reload_request = true;
SetLatch(MyLatch);
errno = save_errno;
}
/*
@ -2703,6 +2711,8 @@ process_pm_reload_request(void)
static void
handle_pm_shutdown_request_signal(SIGNAL_ARGS)
{
int save_errno = errno;
switch (postgres_signal_arg)
{
case SIGTERM:
@ -2719,6 +2729,8 @@ handle_pm_shutdown_request_signal(SIGNAL_ARGS)
break;
}
SetLatch(MyLatch);
errno = save_errno;
}
/*
@ -2878,8 +2890,12 @@ process_pm_shutdown_request(void)
static void
handle_pm_child_exit_signal(SIGNAL_ARGS)
{
int save_errno = errno;
pending_pm_child_exit = true;
SetLatch(MyLatch);
errno = save_errno;
}
/*

View File

@ -19,6 +19,8 @@
*/
#include "postgres.h"
#include <unistd.h>
#include "access/xlog.h"
#include "access/xlogrecovery.h"
#include "access/xlogutils.h"
@ -93,27 +95,52 @@ static void StartupProcExit(int code, Datum arg);
static void
StartupProcTriggerHandler(SIGNAL_ARGS)
{
int save_errno = errno;
promote_signaled = true;
WakeupRecovery();
errno = save_errno;
}
/* SIGHUP: set flag to re-read config file at next convenient time */
static void
StartupProcSigHupHandler(SIGNAL_ARGS)
{
int save_errno = errno;
got_SIGHUP = true;
WakeupRecovery();
errno = save_errno;
}
/* SIGTERM: set flag to abort redo and exit */
static void
StartupProcShutdownHandler(SIGNAL_ARGS)
{
int save_errno = errno;
if (in_restore_command)
{
/*
* 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
shutdown_requested = true;
WakeupRecovery();
errno = save_errno;
}
/*

View File

@ -1642,6 +1642,10 @@ RemoveLogrotateSignalFiles(void)
static void
sigUsr1Handler(SIGNAL_ARGS)
{
int save_errno = errno;
rotation_requested = true;
SetLatch(MyLatch);
errno = save_errno;
}

View File

@ -3476,8 +3476,12 @@ HandleWalSndInitStopping(void)
static void
WalSndLastCycleHandler(SIGNAL_ARGS)
{
int save_errno = errno;
got_SIGUSR2 = true;
SetLatch(MyLatch);
errno = save_errno;
}
/* Set up signal handlers */

View File

@ -2243,8 +2243,12 @@ GetNumRegisteredWaitEvents(WaitEventSet *set)
static void
latch_sigurg_handler(SIGNAL_ARGS)
{
int save_errno = errno;
if (waiting)
sendSelfPipeByte();
errno = save_errno;
}
/* Send one byte to the self-pipe, to wake up WaitLatch */

View File

@ -638,6 +638,8 @@ CheckProcSignal(ProcSignalReason reason)
void
procsignal_sigusr1_handler(SIGNAL_ARGS)
{
int save_errno = errno;
if (CheckProcSignal(PROCSIG_CATCHUP_INTERRUPT))
HandleCatchupInterrupt();
@ -681,4 +683,6 @@ procsignal_sigusr1_handler(SIGNAL_ARGS)
HandleRecoveryConflictInterrupt(PROCSIG_RECOVERY_CONFLICT_BUFFERPIN);
SetLatch(MyLatch);
errno = save_errno;
}

View File

@ -2970,6 +2970,8 @@ quickdie(SIGNAL_ARGS)
void
die(SIGNAL_ARGS)
{
int save_errno = errno;
/* Don't joggle the elbow of proc_exit */
if (!proc_exit_inprogress)
{
@ -2991,6 +2993,8 @@ die(SIGNAL_ARGS)
*/
if (DoingCommandRead && whereToSendOutput != DestRemote)
ProcessInterrupts();
errno = save_errno;
}
/*
@ -3000,6 +3004,8 @@ die(SIGNAL_ARGS)
void
StatementCancelHandler(SIGNAL_ARGS)
{
int save_errno = errno;
/*
* 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 */
SetLatch(MyLatch);
errno = save_errno;
}
/* signal handler for floating point exception */

View File

@ -3737,3 +3737,31 @@ write_stderr(const char *fmt,...)
#endif
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;
}
}

View File

@ -363,6 +363,8 @@ schedule_alarm(TimestampTz now)
static void
handle_sig_alarm(SIGNAL_ARGS)
{
int save_errno = errno;
/*
* Bump the holdoff counter, to make sure nothing we call will process
* interrupts directly. No timeout handler should do that, but these
@ -450,6 +452,8 @@ handle_sig_alarm(SIGNAL_ARGS)
}
RESUME_INTERRUPTS();
errno = save_errno;
}

View File

@ -1868,7 +1868,7 @@ selectDumpableType(TypeInfo *tyinfo, Archive *fout)
return;
}
/* skip auto-generated array and multirange types */
/* skip auto-generated array types */
if (tyinfo->isArray || tyinfo->isMultirange)
{
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
* 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
* base type here, since getTypes may not have processed it yet.)
* type. (We cannot reliably look up the base type here, since
* getTypes may not have processed it yet.)
*/
}
@ -5770,7 +5770,7 @@ getTypes(Archive *fout, int *numTypes)
else
tyinfo[i].isArray = false;
if (tyinfo[i].typtype == TYPTYPE_MULTIRANGE)
if (tyinfo[i].typtype == 'm')
tyinfo[i].isMultirange = true;
else
tyinfo[i].isMultirange = false;

View File

@ -152,6 +152,7 @@ ResetCancelConn(void)
static void
handle_sigint(SIGNAL_ARGS)
{
int save_errno = errno;
char errbuf[256];
CancelRequested = true;
@ -172,6 +173,8 @@ handle_sigint(SIGNAL_ARGS)
write_stderr(errbuf);
}
}
errno = save_errno; /* just in case the write changed it */
}
/*

View File

@ -57,6 +57,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 202402142
#define CATALOG_VERSION_NO 202402141
#endif

View File

@ -536,4 +536,10 @@ extern void write_jsonlog(ErrorData *edata);
*/
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 */

View File

@ -46,105 +46,23 @@
#include "c.h"
#include <signal.h>
#ifndef FRONTEND
#include <unistd.h>
#endif
#ifndef FRONTEND
#include "libpq/pqsignal.h"
#include "miscadmin.h"
#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"
*
* 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
pqsignal(int signo, pqsigfunc func)
{
pqsigfunc orig_func = pqsignal_handlers[signo]; /* assumed atomic */
#if !(defined(WIN32) && defined(FRONTEND))
struct sigaction act,
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;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_RESTART;
@ -154,15 +72,9 @@ pqsignal(int signo, pqsigfunc func)
#endif
if (sigaction(signo, &act, &oact) < 0)
return SIG_ERR;
else if (oact.sa_handler == wrapper_handler)
return orig_func;
else
return oact.sa_handler;
#else
/* Forward to Windows native signal system. */
if ((ret = signal(signo, func)) == wrapper_handler)
return orig_func;
else
return ret;
return signal(signo, func);
#endif
}

View File

@ -171,7 +171,7 @@ $standby1->safe_psql('postgres', "SELECT pg_sync_replication_slots();");
# flagged as 'synced'
is( $standby1->safe_psql(
'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",
'logical slots have synced as true on standby');
@ -227,13 +227,6 @@ $standby1->reload;
$subscriber1->safe_psql('postgres',
"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');
# 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'
is( $standby1->safe_psql(
'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",
'logical slot is re-synced');

View File

@ -144,6 +144,7 @@ owner of sequence deptest_a_seq
owner of table deptest
owner of function deptest_func()
owner of type deptest_enum
owner of type deptest_multirange
owner of type deptest_range
owner of table deptest2
owner of sequence ss1

View File

@ -683,23 +683,3 @@ SELECT gist_stratnum_identity(18::smallint);
18
(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;

View File

@ -3115,36 +3115,6 @@ select _textrange1(textrange2('a','z')) @> 'b'::text;
drop type textrange1;
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
--
create function anyarray_anymultirange_func(a anyarray, r anymultirange)

View File

@ -254,14 +254,3 @@ FROM pg_walfile_name_offset('0/0'::pg_lsn + :segment_size - 1),
-- test stratnum support functions
SELECT gist_stratnum_identity(3::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;

View File

@ -700,27 +700,6 @@ select _textrange1(textrange2('a','z')) @> 'b'::text;
drop type textrange1;
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
--