aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2013-06-13 13:11:40 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2013-06-13 13:11:40 -0400
commitcf0f08e03b51c58e72d56d52a9c07ffbe808a3f1 (patch)
tree0ae5082709f70a1a8528270706fe2f0d24224fb4
parente19c932edf199068895b4e3bc53218db59407f0b (diff)
downloadpostgresql-cf0f08e03b51c58e72d56d52a9c07ffbe808a3f1.tar.gz
postgresql-cf0f08e03b51c58e72d56d52a9c07ffbe808a3f1.zip
Only install a portal's ResourceOwner if it actually has one.
In most scenarios a portal without a ResourceOwner is dead and not subject to any further execution, but a portal for a cursor WITH HOLD remains in existence with no ResourceOwner after the creating transaction is over. In this situation, if we attempt to "execute" the portal directly to fetch data from it, we were setting CurrentResourceOwner to NULL, leading to a segfault if the datatype output code did anything that required a resource owner (such as trying to fetch system catalog entries that weren't already cached). The case appears to be impossible to provoke with stock libpq, but psqlODBC at least is able to cause it when working with held cursors. Simplest fix is to just skip the assignment to CurrentResourceOwner, so that any resources used by the data output operations will be managed by the transaction-level resource owner instead. For consistency I changed all the places that install a portal's resowner as current, even though some of them are probably not reachable with a held cursor's portal. Per report from Joshua Berry (with thanks to Hiroshi Inoue for developing a self-contained test case). Back-patch to all supported versions.
-rw-r--r--src/backend/commands/portalcmds.c6
-rw-r--r--src/backend/tcop/pquery.c9
2 files changed, 10 insertions, 5 deletions
diff --git a/src/backend/commands/portalcmds.c b/src/backend/commands/portalcmds.c
index 656a61cbdeb..314f91501df 100644
--- a/src/backend/commands/portalcmds.c
+++ b/src/backend/commands/portalcmds.c
@@ -274,7 +274,8 @@ PortalCleanup(Portal portal)
saveResourceOwner = CurrentResourceOwner;
PG_TRY();
{
- CurrentResourceOwner = portal->resowner;
+ if (portal->resowner)
+ CurrentResourceOwner = portal->resowner;
ExecutorFinish(queryDesc);
ExecutorEnd(queryDesc);
FreeQueryDesc(queryDesc);
@@ -349,7 +350,8 @@ PersistHoldablePortal(Portal portal)
PG_TRY();
{
ActivePortal = portal;
- CurrentResourceOwner = portal->resowner;
+ if (portal->resowner)
+ CurrentResourceOwner = portal->resowner;
PortalContext = PortalGetHeapMemory(portal);
MemoryContextSwitchTo(PortalContext);
diff --git a/src/backend/tcop/pquery.c b/src/backend/tcop/pquery.c
index 0e2494fa8a5..e8f557c1a1e 100644
--- a/src/backend/tcop/pquery.c
+++ b/src/backend/tcop/pquery.c
@@ -478,7 +478,8 @@ PortalStart(Portal portal, ParamListInfo params, Snapshot snapshot)
PG_TRY();
{
ActivePortal = portal;
- CurrentResourceOwner = portal->resowner;
+ if (portal->resowner)
+ CurrentResourceOwner = portal->resowner;
PortalContext = PortalGetHeapMemory(portal);
oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
@@ -761,7 +762,8 @@ PortalRun(Portal portal, long count, bool isTopLevel,
PG_TRY();
{
ActivePortal = portal;
- CurrentResourceOwner = portal->resowner;
+ if (portal->resowner)
+ CurrentResourceOwner = portal->resowner;
PortalContext = PortalGetHeapMemory(portal);
MemoryContextSwitchTo(PortalContext);
@@ -1410,7 +1412,8 @@ PortalRunFetch(Portal portal,
PG_TRY();
{
ActivePortal = portal;
- CurrentResourceOwner = portal->resowner;
+ if (portal->resowner)
+ CurrentResourceOwner = portal->resowner;
PortalContext = PortalGetHeapMemory(portal);
oldContext = MemoryContextSwitchTo(PortalContext);