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

Commit 52aa334

Browse files
committed
PL/Python: Fix crash in functions returning SETOF and using SPI
Allocate PLyResultObject.tupdesc in TopMemoryContext, because its lifetime is the lifetime of the Python object and it shouldn't be freed by some other memory context, such as one controlled by SPI. We trust that the Python object will clean up its own memory. Before, this would crash the included regression test case by trying to use memory that was already freed. reported by Asif Naeem, analysis by Tom Lane
1 parent e9605a0 commit 52aa334

File tree

3 files changed

+39
-0
lines changed

3 files changed

+39
-0
lines changed

src/pl/plpython/expected/plpython_setof.out

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,3 +124,19 @@ SELECT test_setof_spi_in_iterator();
124124
World
125125
(4 rows)
126126

127+
-- setof function with an SPI result set (used to crash because of
128+
-- memory management issues across multiple calls)
129+
CREATE OR REPLACE FUNCTION get_user_records()
130+
RETURNS SETOF users
131+
AS $$
132+
return plpy.execute("SELECT * FROM users ORDER BY username")
133+
$$ LANGUAGE plpythonu;
134+
SELECT get_user_records();
135+
get_user_records
136+
----------------------
137+
(jane,doe,j_doe,1)
138+
(john,doe,johnd,2)
139+
(rick,smith,slash,4)
140+
(willem,doe,w_doe,3)
141+
(4 rows)
142+

src/pl/plpython/plpy_spi.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "executor/spi_priv.h"
1212
#include "mb/pg_wchar.h"
1313
#include "parser/parse_type.h"
14+
#include "utils/memutils.h"
1415
#include "utils/syscache.h"
1516

1617
#include "plpython.h"
@@ -403,7 +404,17 @@ PLy_spi_execute_fetch_result(SPITupleTable *tuptable, int rows, int status)
403404
oldcontext = CurrentMemoryContext;
404405
PG_TRY();
405406
{
407+
MemoryContext oldcontext2;
408+
409+
/*
410+
* Save tuple descriptor for later use by result set metadata
411+
* functions. Save it in TopMemoryContext so that it survives
412+
* outside of an SPI context. We trust that PLy_result_dealloc()
413+
* will clean it up when the time is right.
414+
*/
415+
oldcontext2 = MemoryContextSwitchTo(TopMemoryContext);
406416
result->tupdesc = CreateTupleDescCopy(tuptable->tupdesc);
417+
MemoryContextSwitchTo(oldcontext2);
407418

408419
if (rows)
409420
{

src/pl/plpython/sql/plpython_setof.sql

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,15 @@ SELECT test_setof_as_iterator(2, 'list');
6262
SELECT test_setof_as_iterator(2, null);
6363

6464
SELECT test_setof_spi_in_iterator();
65+
66+
67+
-- setof function with an SPI result set (used to crash because of
68+
-- memory management issues across multiple calls)
69+
70+
CREATE OR REPLACE FUNCTION get_user_records()
71+
RETURNS SETOF users
72+
AS $$
73+
return plpy.execute("SELECT * FROM users ORDER BY username")
74+
$$ LANGUAGE plpythonu;
75+
76+
SELECT get_user_records();

0 commit comments

Comments
 (0)