Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit29dfffa

Browse files
committed
Repair memory leaks in plpython.
PLy_spi_execute_plan (PLyPlan.execute) and PLy_cursor_plan(plpy.cursor) use PLy_output_convert to convert Python valuesinto Datums that can be passed to the query-to-execute. But theyfailed to pay much attention to its warning that it can leave "cruftgenerated along the way" behind. Repeated use of these methods canresult in a substantial memory leak for the duration of the callingplpython function.To fix, make a temporary memory context to invoke PLy_output_convertin. This also lets us get rid of the rather fragile code that washere for retail pfree's of the converted Datums. Indeed, we don'tneed the PLyPlanObject.values field anymore at all, though I left itin place in the back branches in the name of ABI stability.Mat Arye and Tom Lane, per report from Mat Arye. Back-patch to allsupported branches.Discussion:https://postgr.es/m/CADsUR0DvVgnZYWwnmKRK65MZg7YLUSTDLV61qdnrwtrAJgU6xw@mail.gmail.com
1 parentca87c41 commit29dfffa

File tree

4 files changed

+49
-64
lines changed

4 files changed

+49
-64
lines changed

‎src/pl/plpython/plpy_cursorobject.c

Lines changed: 24 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,6 @@ PLy_cursor_plan(PyObject *ob, PyObject *args)
140140
{
141141
PLyCursorObject*cursor;
142142
volatileintnargs;
143-
inti;
144143
PLyPlanObject*plan;
145144
PLyExecutionContext*exec_ctx=PLy_current_execution_context();
146145
volatileMemoryContextoldcontext;
@@ -199,13 +198,30 @@ PLy_cursor_plan(PyObject *ob, PyObject *args)
199198
PG_TRY();
200199
{
201200
Portalportal;
201+
MemoryContexttmpcontext;
202+
Datum*volatilevalues;
202203
char*volatilenulls;
203204
volatileintj;
204205

206+
/*
207+
* Converted arguments and associated cruft will be in this context,
208+
* which is local to our subtransaction.
209+
*/
210+
tmpcontext=AllocSetContextCreate(CurTransactionContext,
211+
"PL/Python temporary context",
212+
ALLOCSET_SMALL_SIZES);
213+
MemoryContextSwitchTo(tmpcontext);
214+
205215
if (nargs>0)
206-
nulls=palloc(nargs*sizeof(char));
216+
{
217+
values= (Datum*)palloc(nargs*sizeof(Datum));
218+
nulls= (char*)palloc(nargs*sizeof(char));
219+
}
207220
else
221+
{
222+
values=NULL;
208223
nulls=NULL;
224+
}
209225

210226
for (j=0;j<nargs;j++)
211227
{
@@ -217,7 +233,7 @@ PLy_cursor_plan(PyObject *ob, PyObject *args)
217233
{
218234
boolisnull;
219235

220-
plan->values[j]=PLy_output_convert(arg,elem,&isnull);
236+
values[j]=PLy_output_convert(arg,elem,&isnull);
221237
nulls[j]=isnull ?'n' :' ';
222238
}
223239
PG_FINALLY(2);
@@ -227,7 +243,9 @@ PLy_cursor_plan(PyObject *ob, PyObject *args)
227243
PG_END_TRY(2);
228244
}
229245

230-
portal=SPI_cursor_open(NULL,plan->plan,plan->values,nulls,
246+
MemoryContextSwitchTo(oldcontext);
247+
248+
portal=SPI_cursor_open(NULL,plan->plan,values,nulls,
231249
exec_ctx->curr_proc->fn_readonly);
232250
if (portal==NULL)
233251
elog(ERROR,"SPI_cursor_open() failed: %s",
@@ -237,40 +255,18 @@ PLy_cursor_plan(PyObject *ob, PyObject *args)
237255

238256
PinPortal(portal);
239257

258+
MemoryContextDelete(tmpcontext);
240259
PLy_spi_subtransaction_commit(oldcontext,oldowner);
241260
}
242261
PG_CATCH();
243262
{
244-
intk;
245-
246-
/* cleanup plan->values array */
247-
for (k=0;k<nargs;k++)
248-
{
249-
if (!plan->args[k].typbyval&&
250-
(plan->values[k]!=PointerGetDatum(NULL)))
251-
{
252-
pfree(DatumGetPointer(plan->values[k]));
253-
plan->values[k]=PointerGetDatum(NULL);
254-
}
255-
}
256-
257263
Py_DECREF(cursor);
258-
264+
/* Subtransaction abort will remove the tmpcontext */
259265
PLy_spi_subtransaction_abort(oldcontext,oldowner);
260266
returnNULL;
261267
}
262268
PG_END_TRY();
263269

264-
for (i=0;i<nargs;i++)
265-
{
266-
if (!plan->args[i].typbyval&&
267-
(plan->values[i]!=PointerGetDatum(NULL)))
268-
{
269-
pfree(DatumGetPointer(plan->values[i]));
270-
plan->values[i]=PointerGetDatum(NULL);
271-
}
272-
}
273-
274270
Assert(cursor->portalname!=NULL);
275271
return (PyObject*)cursor;
276272
}

‎src/pl/plpython/plpy_planobject.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ PLy_plan_new(void)
5454
ob->plan=NULL;
5555
ob->nargs=0;
5656
ob->types=NULL;
57-
ob->values=NULL;
5857
ob->args=NULL;
5958
ob->mcxt=NULL;
6059

‎src/pl/plpython/plpy_planobject.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ typedef struct PLyPlanObject
1515
SPIPlanPtrplan;
1616
intnargs;
1717
Oid*types;
18-
Datum*values;
1918
PLyObToDatum*args;
2019
MemoryContextmcxt;
2120
}PLyPlanObject;

‎src/pl/plpython/plpy_spi.c

Lines changed: 25 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ PLy_spi_prepare(PyObject *self, PyObject *args)
6666

6767
plan->nargs=nargs;
6868
plan->types=nargs ?palloc0(sizeof(Oid)*nargs) :NULL;
69-
plan->values=nargs ?palloc0(sizeof(Datum)*nargs) :NULL;
7069
plan->args=nargs ?palloc0(sizeof(PLyObToDatum)*nargs) :NULL;
7170

7271
MemoryContextSwitchTo(oldcontext);
@@ -172,8 +171,7 @@ PyObject *
172171
PLy_spi_execute_plan(PyObject*ob,PyObject*list,longlimit)
173172
{
174173
volatileintnargs;
175-
inti,
176-
rv;
174+
intrv;
177175
PLyPlanObject*plan;
178176
volatileMemoryContextoldcontext;
179177
volatileResourceOwneroldowner;
@@ -219,13 +217,30 @@ PLy_spi_execute_plan(PyObject *ob, PyObject *list, long limit)
219217
PG_TRY();
220218
{
221219
PLyExecutionContext*exec_ctx=PLy_current_execution_context();
220+
MemoryContexttmpcontext;
221+
Datum*volatilevalues;
222222
char*volatilenulls;
223223
volatileintj;
224224

225+
/*
226+
* Converted arguments and associated cruft will be in this context,
227+
* which is local to our subtransaction.
228+
*/
229+
tmpcontext=AllocSetContextCreate(CurTransactionContext,
230+
"PL/Python temporary context",
231+
ALLOCSET_SMALL_SIZES);
232+
MemoryContextSwitchTo(tmpcontext);
233+
225234
if (nargs>0)
226-
nulls=palloc(nargs*sizeof(char));
235+
{
236+
values= (Datum*)palloc(nargs*sizeof(Datum));
237+
nulls= (char*)palloc(nargs*sizeof(char));
238+
}
227239
else
240+
{
241+
values=NULL;
228242
nulls=NULL;
243+
}
229244

230245
for (j=0;j<nargs;j++)
231246
{
@@ -237,7 +252,7 @@ PLy_spi_execute_plan(PyObject *ob, PyObject *list, long limit)
237252
{
238253
boolisnull;
239254

240-
plan->values[j]=PLy_output_convert(arg,elem,&isnull);
255+
values[j]=PLy_output_convert(arg,elem,&isnull);
241256
nulls[j]=isnull ?'n' :' ';
242257
}
243258
PG_FINALLY(2);
@@ -247,47 +262,23 @@ PLy_spi_execute_plan(PyObject *ob, PyObject *list, long limit)
247262
PG_END_TRY(2);
248263
}
249264

250-
rv=SPI_execute_plan(plan->plan,plan->values,nulls,
265+
MemoryContextSwitchTo(oldcontext);
266+
267+
rv=SPI_execute_plan(plan->plan,values,nulls,
251268
exec_ctx->curr_proc->fn_readonly,limit);
252269
ret=PLy_spi_execute_fetch_result(SPI_tuptable,SPI_processed,rv);
253270

254-
if (nargs>0)
255-
pfree(nulls);
256-
271+
MemoryContextDelete(tmpcontext);
257272
PLy_spi_subtransaction_commit(oldcontext,oldowner);
258273
}
259274
PG_CATCH();
260275
{
261-
intk;
262-
263-
/*
264-
* cleanup plan->values array
265-
*/
266-
for (k=0;k<nargs;k++)
267-
{
268-
if (!plan->args[k].typbyval&&
269-
(plan->values[k]!=PointerGetDatum(NULL)))
270-
{
271-
pfree(DatumGetPointer(plan->values[k]));
272-
plan->values[k]=PointerGetDatum(NULL);
273-
}
274-
}
275-
276+
/* Subtransaction abort will remove the tmpcontext */
276277
PLy_spi_subtransaction_abort(oldcontext,oldowner);
277278
returnNULL;
278279
}
279280
PG_END_TRY();
280281

281-
for (i=0;i<nargs;i++)
282-
{
283-
if (!plan->args[i].typbyval&&
284-
(plan->values[i]!=PointerGetDatum(NULL)))
285-
{
286-
pfree(DatumGetPointer(plan->values[i]));
287-
plan->values[i]=PointerGetDatum(NULL);
288-
}
289-
}
290-
291282
if (rv<0)
292283
{
293284
PLy_exception_set(PLy_exc_spi_error,

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp