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

Commit8c75ad4

Browse files
committed
Fix memory leaks in PL/Python.
Previously, plpython was in the habit of allocating a lot of stuff inTopMemoryContext, and it was very slipshod about making sure that stuffgot cleaned up; in particular, use of TopMemoryContext as fn_mcxt forfunction calls represents an unfixable leak, since we generally don'tknow what the called function might have allocated in fn_mcxt. Thisresults in session-lifespan leakage in certain usage scenarios, as forexample in a case reported by Ed Behn back in July.To fix, get rid of all the retail allocations in TopMemoryContext.All long-lived allocations are now made in sub-contexts that areassociated with specific objects (either pl/python procedures, orPython-visible objects such as cursors and plans). We can clean theseup when the associated object is deleted.I went so far as to get rid of PLy_malloc completely. There were acouple of places where it could still have been used safely, but onthe whole it was just an invitation to bad coding.Haribabu Kommi, based on a draft patch by Heikki Linnakangas;some further work by me
1 parent64b2e7a commit8c75ad4

15 files changed

+221
-223
lines changed

‎src/pl/plpython/plpy_cursorobject.c

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include"access/xact.h"
1010
#include"mb/pg_wchar.h"
11+
#include"utils/memutils.h"
1112

1213
#include"plpython.h"
1314

@@ -111,7 +112,12 @@ PLy_cursor_query(const char *query)
111112
returnNULL;
112113
cursor->portalname=NULL;
113114
cursor->closed= false;
114-
PLy_typeinfo_init(&cursor->result);
115+
cursor->mcxt=AllocSetContextCreate(TopMemoryContext,
116+
"PL/Python cursor context",
117+
ALLOCSET_DEFAULT_MINSIZE,
118+
ALLOCSET_DEFAULT_INITSIZE,
119+
ALLOCSET_DEFAULT_MAXSIZE);
120+
PLy_typeinfo_init(&cursor->result,cursor->mcxt);
115121

116122
oldcontext=CurrentMemoryContext;
117123
oldowner=CurrentResourceOwner;
@@ -139,7 +145,7 @@ PLy_cursor_query(const char *query)
139145
elog(ERROR,"SPI_cursor_open() failed: %s",
140146
SPI_result_code_string(SPI_result));
141147

142-
cursor->portalname=PLy_strdup(portal->name);
148+
cursor->portalname=MemoryContextStrdup(cursor->mcxt,portal->name);
143149

144150
PLy_spi_subtransaction_commit(oldcontext,oldowner);
145151
}
@@ -200,7 +206,12 @@ PLy_cursor_plan(PyObject *ob, PyObject *args)
200206
returnNULL;
201207
cursor->portalname=NULL;
202208
cursor->closed= false;
203-
PLy_typeinfo_init(&cursor->result);
209+
cursor->mcxt=AllocSetContextCreate(TopMemoryContext,
210+
"PL/Python cursor context",
211+
ALLOCSET_DEFAULT_MINSIZE,
212+
ALLOCSET_DEFAULT_INITSIZE,
213+
ALLOCSET_DEFAULT_MAXSIZE);
214+
PLy_typeinfo_init(&cursor->result,cursor->mcxt);
204215

205216
oldcontext=CurrentMemoryContext;
206217
oldowner=CurrentResourceOwner;
@@ -261,7 +272,7 @@ PLy_cursor_plan(PyObject *ob, PyObject *args)
261272
elog(ERROR,"SPI_cursor_open() failed: %s",
262273
SPI_result_code_string(SPI_result));
263274

264-
cursor->portalname=PLy_strdup(portal->name);
275+
cursor->portalname=MemoryContextStrdup(cursor->mcxt,portal->name);
265276

266277
PLy_spi_subtransaction_commit(oldcontext,oldowner);
267278
}
@@ -315,12 +326,13 @@ PLy_cursor_dealloc(PyObject *arg)
315326

316327
if (PortalIsValid(portal))
317328
SPI_cursor_close(portal);
329+
cursor->closed= true;
330+
}
331+
if (cursor->mcxt)
332+
{
333+
MemoryContextDelete(cursor->mcxt);
334+
cursor->mcxt=NULL;
318335
}
319-
320-
PLy_free(cursor->portalname);
321-
cursor->portalname=NULL;
322-
323-
PLy_typeinfo_dealloc(&cursor->result);
324336
arg->ob_type->tp_free(arg);
325337
}
326338

‎src/pl/plpython/plpy_cursorobject.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ typedef struct PLyCursorObject
1414
char*portalname;
1515
PLyTypeInforesult;
1616
boolclosed;
17+
MemoryContextmcxt;
1718
}PLyCursorObject;
1819

1920
externvoidPLy_cursor_init_type(void);

‎src/pl/plpython/plpy_exec.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -852,6 +852,6 @@ PLy_abort_open_subtransactions(int save_subxact_level)
852852

853853
MemoryContextSwitchTo(subtransactiondata->oldcontext);
854854
CurrentResourceOwner=subtransactiondata->oldowner;
855-
PLy_free(subtransactiondata);
855+
pfree(subtransactiondata);
856856
}
857857
}

‎src/pl/plpython/plpy_main.c

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,12 @@ plpython_inline_handler(PG_FUNCTION_ARGS)
277277
flinfo.fn_mcxt=CurrentMemoryContext;
278278

279279
MemSet(&proc,0,sizeof(PLyProcedure));
280-
proc.pyname=PLy_strdup("__plpython_inline_block");
280+
proc.mcxt=AllocSetContextCreate(TopMemoryContext,
281+
"__plpython_inline_block",
282+
ALLOCSET_DEFAULT_MINSIZE,
283+
ALLOCSET_DEFAULT_INITSIZE,
284+
ALLOCSET_DEFAULT_MAXSIZE);
285+
proc.pyname=MemoryContextStrdup(proc.mcxt,"__plpython_inline_block");
281286
proc.langid=codeblock->langOid;
282287
proc.result.out.d.typoid=VOIDOID;
283288

@@ -364,17 +369,32 @@ PLy_current_execution_context(void)
364369
returnPLy_execution_contexts;
365370
}
366371

372+
MemoryContext
373+
PLy_get_scratch_context(PLyExecutionContext*context)
374+
{
375+
/*
376+
* A scratch context might never be needed in a given plpython procedure,
377+
* so allocate it on first request.
378+
*/
379+
if (context->scratch_ctx==NULL)
380+
context->scratch_ctx=
381+
AllocSetContextCreate(TopTransactionContext,
382+
"PL/Python scratch context",
383+
ALLOCSET_DEFAULT_MINSIZE,
384+
ALLOCSET_DEFAULT_INITSIZE,
385+
ALLOCSET_DEFAULT_MAXSIZE);
386+
returncontext->scratch_ctx;
387+
}
388+
367389
staticPLyExecutionContext*
368390
PLy_push_execution_context(void)
369391
{
370-
PLyExecutionContext*context=PLy_malloc(sizeof(PLyExecutionContext));
392+
PLyExecutionContext*context;
371393

394+
context= (PLyExecutionContext*)
395+
MemoryContextAlloc(TopTransactionContext,sizeof(PLyExecutionContext));
372396
context->curr_proc=NULL;
373-
context->scratch_ctx=AllocSetContextCreate(TopTransactionContext,
374-
"PL/Python scratch context",
375-
ALLOCSET_DEFAULT_MINSIZE,
376-
ALLOCSET_DEFAULT_INITSIZE,
377-
ALLOCSET_DEFAULT_MAXSIZE);
397+
context->scratch_ctx=NULL;
378398
context->next=PLy_execution_contexts;
379399
PLy_execution_contexts=context;
380400
returncontext;
@@ -390,6 +410,7 @@ PLy_pop_execution_context(void)
390410

391411
PLy_execution_contexts=context->next;
392412

393-
MemoryContextDelete(context->scratch_ctx);
394-
PLy_free(context);
413+
if (context->scratch_ctx)
414+
MemoryContextDelete(context->scratch_ctx);
415+
pfree(context);
395416
}

‎src/pl/plpython/plpy_main.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,7 @@ typedef struct PLyExecutionContext
2525
/* Get the current execution context */
2626
externPLyExecutionContext*PLy_current_execution_context(void);
2727

28+
/* Get the scratch memory context for specified execution context */
29+
externMemoryContextPLy_get_scratch_context(PLyExecutionContext*context);
30+
2831
#endif/* PLPY_MAIN_H */

‎src/pl/plpython/plpy_planobject.c

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include"plpy_planobject.h"
1212

1313
#include"plpy_elog.h"
14+
#include"utils/memutils.h"
1415

1516

1617
staticvoidPLy_plan_dealloc(PyObject*arg);
@@ -80,6 +81,7 @@ PLy_plan_new(void)
8081
ob->types=NULL;
8182
ob->values=NULL;
8283
ob->args=NULL;
84+
ob->mcxt=NULL;
8385

8486
return (PyObject*)ob;
8587
}
@@ -96,20 +98,15 @@ PLy_plan_dealloc(PyObject *arg)
9698
PLyPlanObject*ob= (PLyPlanObject*)arg;
9799

98100
if (ob->plan)
101+
{
99102
SPI_freeplan(ob->plan);
100-
if (ob->types)
101-
PLy_free(ob->types);
102-
if (ob->values)
103-
PLy_free(ob->values);
104-
if (ob->args)
103+
ob->plan=NULL;
104+
}
105+
if (ob->mcxt)
105106
{
106-
inti;
107-
108-
for (i=0;i<ob->nargs;i++)
109-
PLy_typeinfo_dealloc(&ob->args[i]);
110-
PLy_free(ob->args);
107+
MemoryContextDelete(ob->mcxt);
108+
ob->mcxt=NULL;
111109
}
112-
113110
arg->ob_type->tp_free(arg);
114111
}
115112

‎src/pl/plpython/plpy_planobject.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ typedef struct PLyPlanObject
1717
Oid*types;
1818
Datum*values;
1919
PLyTypeInfo*args;
20+
MemoryContextmcxt;
2021
}PLyPlanObject;
2122

2223
externvoidPLy_plan_init_type(void);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp