8000 Only install a portal's ResourceOwner if it actually has one. · sqlparser/postgres@a335531 · GitHub
[go: up one dir, main page]

Skip to content
8000

Commit a335531

Browse files
committed
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.
1 parent 0da76f3 commit a335531

File tree

2 files changed

+10
-5
lines changed

2 files changed

+10
-5
lines changed

src/backend/commands/portalcmds.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,8 @@ PortalCleanup(Portal portal)
263263
saveResourceOwner = CurrentResourceOwner;
264264
PG_TRY();
265265
{
266-
CurrentResourceOwner = portal->resowner;
266+
if (portal->resowner)
267+
CurrentResourceOwner = portal->resowner;
267268
/* we do not need AfterTriggerEndQuery() here */
268269
ExecutorEnd(queryDesc);
269270
FreeQueryDesc(queryDesc);
@@ -338,7 +339,8 @@ PersistHoldablePortal(Portal portal)
338339
PG_TRY();
339340
{
340341
ActivePortal = portal;
341-
CurrentResourceOwner = portal->resowner;
342+
if (portal->resowner)
343+
CurrentResourceOwner = portal->resowner;
342344
PortalContext = PortalGetHeapMemory(portal);
343345

344346
MemoryContextSwitchTo(PortalContext);

src/backend/tcop/pquery.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,8 @@ PortalStart(Portal portal, ParamListInfo params, Snapshot snapshot)
479479
PG_TRY();
480480
{
481481
ActivePortal = portal;
482-
CurrentResourceOwner = portal->resowner;
482+
if (portal->resowner)
483+
CurrentResourceOwner = portal->resowner;
483484
PortalContext = PortalGetHeapMemory(portal);
484485

485486
oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
@@ -768,7 +769,8 @@ PortalRun(Portal portal, long count, bool isTopLevel,
768769
PG_TRY();
769770
{
770771
ActivePortal = portal;
771-
CurrentResourceOwner = portal->resowner;
772+
if (portal->resowner)
773+
CurrentResourceOwner = portal->resowner;
772774
PortalContext = PortalGetHeapMemory(portal);
773775

774776
MemoryContextSwitchTo(PortalContext);
@@ -1375,7 +1377,8 @@ PortalRunFetch(Portal portal,
13751377
PG_TRY();
13761378
{
13771379
ActivePortal = portal;
1378-
CurrentResourceOwner = portal->resowner;
1380+
if (portal->resowner)
1381+
CurrentResourceOwner = portal->resowner;
13791382
PortalContext = PortalGetHeapMemory(portal);
13801383

13811384
oldContext = MemoryContextSwitchTo(PortalContext);

0 commit comments

Comments
 (0)
0