diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2019-03-18 17:54:24 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2019-03-18 17:54:41 -0400 |
commit | f2004f19ed9c9228d3ea2b12379ccb4b9212641f (patch) | |
tree | e624dbef56a9b39f12341011d1a8b1ef0811aa24 | |
parent | 11180a5015e9c6299ee732fa587b3a8bc6dca6b2 (diff) | |
download | postgresql-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
-rw-r--r-- | src/backend/access/common/printtup.c | 12 |
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; |