mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-21 08:29:39 +08:00
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
This commit is contained in:
parent
e9605a039b
commit
52aa334fcd
@ -124,3 +124,19 @@ SELECT test_setof_spi_in_iterator();
|
|||||||
World
|
World
|
||||||
(4 rows)
|
(4 rows)
|
||||||
|
|
||||||
|
-- setof function with an SPI result set (used to crash because of
|
||||||
|
-- memory management issues across multiple calls)
|
||||||
|
CREATE OR REPLACE FUNCTION get_user_records()
|
||||||
|
RETURNS SETOF users
|
||||||
|
AS $$
|
||||||
|
return plpy.execute("SELECT * FROM users ORDER BY username")
|
||||||
|
$$ LANGUAGE plpythonu;
|
||||||
|
SELECT get_user_records();
|
||||||
|
get_user_records
|
||||||
|
----------------------
|
||||||
|
(jane,doe,j_doe,1)
|
||||||
|
(john,doe,johnd,2)
|
||||||
|
(rick,smith,slash,4)
|
||||||
|
(willem,doe,w_doe,3)
|
||||||
|
(4 rows)
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include "executor/spi_priv.h"
|
#include "executor/spi_priv.h"
|
||||||
#include "mb/pg_wchar.h"
|
#include "mb/pg_wchar.h"
|
||||||
#include "parser/parse_type.h"
|
#include "parser/parse_type.h"
|
||||||
|
#include "utils/memutils.h"
|
||||||
#include "utils/syscache.h"
|
#include "utils/syscache.h"
|
||||||
|
|
||||||
#include "plpython.h"
|
#include "plpython.h"
|
||||||
@ -403,7 +404,17 @@ PLy_spi_execute_fetch_result(SPITupleTable *tuptable, int rows, int status)
|
|||||||
oldcontext = CurrentMemoryContext;
|
oldcontext = CurrentMemoryContext;
|
||||||
PG_TRY();
|
PG_TRY();
|
||||||
{
|
{
|
||||||
|
MemoryContext oldcontext2;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save tuple descriptor for later use by result set metadata
|
||||||
|
* functions. Save it in TopMemoryContext so that it survives
|
||||||
|
* outside of an SPI context. We trust that PLy_result_dealloc()
|
||||||
|
* will clean it up when the time is right.
|
||||||
|
*/
|
||||||
|
oldcontext2 = MemoryContextSwitchTo(TopMemoryContext);
|
||||||
result->tupdesc = CreateTupleDescCopy(tuptable->tupdesc);
|
result->tupdesc = CreateTupleDescCopy(tuptable->tupdesc);
|
||||||
|
MemoryContextSwitchTo(oldcontext2);
|
||||||
|
|
||||||
if (rows)
|
if (rows)
|
||||||
{
|
{
|
||||||
|
@ -62,3 +62,15 @@ SELECT test_setof_as_iterator(2, 'list');
|
|||||||
SELECT test_setof_as_iterator(2, null);
|
SELECT test_setof_as_iterator(2, null);
|
||||||
|
|
||||||
SELECT test_setof_spi_in_iterator();
|
SELECT test_setof_spi_in_iterator();
|
||||||
|
|
||||||
|
|
||||||
|
-- setof function with an SPI result set (used to crash because of
|
||||||
|
-- memory management issues across multiple calls)
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION get_user_records()
|
||||||
|
RETURNS SETOF users
|
||||||
|
AS $$
|
||||||
|
return plpy.execute("SELECT * FROM users ORDER BY username")
|
||||||
|
$$ LANGUAGE plpythonu;
|
||||||
|
|
||||||
|
SELECT get_user_records();
|
||||||
|
Loading…
Reference in New Issue
Block a user