plpgsql leaking memory when stringifying datums

From: Jan Urbański <wulczer(at)wulczer(dot)org>
To: Postgres - Hackers <pgsql-hackers(at)postgresql(dot)org>
Subject: plpgsql leaking memory when stringifying datums
Date: 2012-02-05 19:07:22
Message-ID: 4F2ED36A.9020907@wulczer.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

While chasing a PL/Python memory leak, I did a few tests with PL/pgSQL
and I think there are places where memory is not freed sufficiently early.

Attached are two functions that when run will make the backend's memory
consumption increase until they finish. With both, the cause is
convert_value_to_string that calls a datum's output function, which for
toasted data results in an allocation.

The proposed patch changes convert_value_to_string to call the output
function in the per-tuple memory context and then copy the result string
back to the original context.

The comment in that function says that callers generally pfree its
result, but that wasn't the case with exec_stmt_raise, so I added a
pfree() there as well.

With that I was still left with a leak in the typecast() test function
and it turns out that sticking a exec_eval_cleanup into exec_move_row
fixed it. The regression tests pass, but I'm not 100% sure if it's
actually safe.

Since convert_value_to_string needed to access the PL/pgSQL's execution
state to get its hands on the per-tuple context, I needed to pass it to
every caller that didn't have it already, which means exec_cast_value
and exec_simple_cast_value. Anyone has a better idea?

The initial diagnosis and proposed solution are by Andres Freund - thanks!

Cheers,
Jan

Attachment Content-Type Size
plpgsql-convert-value-leak.patch text/x-diff 13.7 KB
plpgsql-leaks.sql application/x-sql 529 bytes

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Tom Lane 2012-02-05 19:18:42 Report: race conditions in WAL replay routines
Previous Message Jan Urbański 2012-02-05 18:54:11 pl/python long-lived allocations in datum->dict transformation