Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit f2004f1

Browse files
committed
Fix memory leak in printtup.c.
Commit f2dec34 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
1 parent 11180a5 commit f2004f1

File tree

1 file changed

+10
-2
lines changed

1 file changed

+10
-2
lines changed

src/backend/access/common/printtup.c

+10-2
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,12 @@ typedef struct
6161
typedef struct
6262
{
6363
DestReceiver pub; /* publicly-known function pointers */
64-
StringInfoData buf; /* output buffer */
6564
Portal portal; /* the Portal we are printing from */
6665
bool sendDescrip; /* send RowDescription at startup? */
6766
TupleDesc attrinfo; /* The attr info we are set up for */
6867
int nattrs;
6968
PrinttupAttrInfo *myinfo; /* Cached info about each attr */
69+
StringInfoData buf; /* output buffer (*not* in tmpcontext) */
7070
MemoryContext tmpcontext; /* Memory context for per-row workspace */
7171
} DR_printtup;
7272

@@ -94,6 +94,7 @@ printtup_create_DR(CommandDest dest)
9494
self->attrinfo = NULL;
9595
self->nattrs = 0;
9696
self->myinfo = NULL;
97+
self->buf.data = NULL;
9798
self->tmpcontext = NULL;
9899

99100
return (DestReceiver *) self;
@@ -132,7 +133,10 @@ printtup_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
132133
DR_printtup *myState = (DR_printtup *) self;
133134
Portal portal = myState->portal;
134135

135-
/* create buffer to be used for all messages */
136+
/*
137+
* Create I/O buffer to be used for all messages. This cannot be inside
138+
* tmpcontext, since we want to re-use it across rows.
139+
*/
136140
initStringInfo(&myState->buf);
137141

138142
/*
@@ -544,6 +548,10 @@ printtup_shutdown(DestReceiver *self)
544548

545549
myState->attrinfo = NULL;
546550

551+
if (myState->buf.data)
552+
pfree(myState->buf.data);
553+
myState->buf.data = NULL;
554+
547555
if (myState->tmpcontext)
548556
MemoryContextDelete(myState->tmpcontext);
549557
myState->tmpcontext = NULL;

0 commit comments

Comments
 (0)