Обсуждение: PL/pgSQL caught exceptions leak memory?

Поиск
Список
Период
Сортировка

PL/pgSQL caught exceptions leak memory?

От
Michael Fuhr
Дата:
Caught exceptions in PL/pgSQL appear to leak memory -- is that
expected?  Here's a contrived test case:

CREATE FUNCTION foo(n integer) RETURNS void AS $$
BEGIN   FOR i IN 1 .. n LOOP       BEGIN           RAISE EXCEPTION 'test';       EXCEPTION         WHEN OTHERS THEN
     NULL;       END;   END LOOP;
 
END;
$$ LANGUAGE plpgsql VOLATILE STRICT;

SELECT foo(200000);

If you watch the backend with top you should see the process size
grow by around 500-600 (512?) bytes per exception caught (you might
need to use more iterations on a fast system to see the effect).

-- 
Michael Fuhr


Re: PL/pgSQL caught exceptions leak memory?

От
Tom Lane
Дата:
Michael Fuhr <mike@fuhr.org> writes:
> Caught exceptions in PL/pgSQL appear to leak memory -- is that
> expected?

This looks a bit messy :-(.  The problem is that if the controlled
statements within the BEGIN block leak any function-local memory
(ie, memory in the "SPI Proc" context of the plpgsql function), this
memory is not reclaimed before we continue execution of the function.

It seems almost impossible to guarantee that no such leaks will occur,
since we might be trying to catch an elog that could have been thrown
from anywhere.  The only practical fix is to run the controlled
statements in a sub-context that could be freed after the PG_CATCH.

The reason that the code currently tries to run the controlled
statements in the same context it was using is that all
pass-by-reference variable values get allocated in the current context.
If this context is thrown away then we'd have dangling pointers, eg
consider
declare x text;begin  ...  begin    x := some-expression;  exception    ... try to use value of x here ...

AFAICS, to make this work we'd have to modify plpgsql so that variable
values are stored in a separate sub-context distinct from what's used as
the "current memory context" while running statements.  This is gonna be
fairly invasive, I fear, and I'm worried about the performance cost of
extra copying too.

Any better ideas out there?
        regards, tom lane