aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2019-03-18 17:54:24 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2019-03-18 17:54:41 -0400
commitf2004f19ed9c9228d3ea2b12379ccb4b9212641f (patch)
treee624dbef56a9b39f12341011d1a8b1ef0811aa24 /src
parent11180a5015e9c6299ee732fa587b3a8bc6dca6b2 (diff)
downloadpostgresql-f2004f19ed9c9228d3ea2b12379ccb4b9212641f.tar.gz
postgresql-f2004f19ed9c9228d3ea2b12379ccb4b9212641f.zip
Fix memory leak in printtup.c.
Commit f2dec34e1 changed things so that printtup's output stringinfo buffer was allocated outside the per-row temporary context, not inside it. This creates a need to free that buffer explicitly when the temp context is freed, but that was overlooked. In most cases, this is all happening inside a portal or executor context that will go away shortly anyhow, but that's not always true. Notably, the stringinfo ends up getting leaked when JDBC uses row-at-a-time fetches. For a query that returns wide rows, that adds up after awhile. Per bug #15700 from Matthias Otterbach. Back-patch to v11 where the faulty code was added. Discussion: https://postgr.es/m/15700-8c408321a87d56bb@postgresql.org
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/common/printtup.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/src/backend/access/common/printtup.c b/src/backend/access/common/printtup.c
index e4ee5c9d345..44add482d3e 100644
--- a/src/backend/access/common/printtup.c
+++ b/src/backend/access/common/printtup.c
@@ -61,12 +61,12 @@ typedef struct
typedef struct
{
DestReceiver pub; /* publicly-known function pointers */
- StringInfoData buf; /* output buffer */
Portal portal; /* the Portal we are printing from */
bool sendDescrip; /* send RowDescription at startup? */
TupleDesc attrinfo; /* The attr info we are set up for */
int nattrs;
PrinttupAttrInfo *myinfo; /* Cached info about each attr */
+ StringInfoData buf; /* output buffer (*not* in tmpcontext) */
MemoryContext tmpcontext; /* Memory context for per-row workspace */
} DR_printtup;
@@ -94,6 +94,7 @@ printtup_create_DR(CommandDest dest)
self->attrinfo = NULL;
self->nattrs = 0;
self->myinfo = NULL;
+ self->buf.data = NULL;
self->tmpcontext = NULL;
return (DestReceiver *) self;
@@ -132,7 +133,10 @@ printtup_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
DR_printtup *myState = (DR_printtup *) self;
Portal portal = myState->portal;
- /* create buffer to be used for all messages */
+ /*
+ * Create I/O buffer to be used for all messages. This cannot be inside
+ * tmpcontext, since we want to re-use it across rows.
+ */
initStringInfo(&myState->buf);
/*
@@ -544,6 +548,10 @@ printtup_shutdown(DestReceiver *self)
myState->attrinfo = NULL;
+ if (myState->buf.data)
+ pfree(myState->buf.data);
+ myState->buf.data = NULL;
+
if (myState->tmpcontext)
MemoryContextDelete(myState->tmpcontext);
myState->tmpcontext = NULL;