Memory leak due to thinko in PL/Python error handling
Tom Lane <tgl@sss.pgh.pa.us>
From: Tom Lane <tgl@sss.pgh.pa.us>
To: pgsql-hackers@lists.postgresql.org
Date: 2025-10-23T01:49:19Z
Lists: pgsql-hackers
Attachments
- fix-plpython-error-handling-leaks-redux.patch (text/x-diff) patch
I have realized that there's an oversight in my recent commit
c6f7f11d8, which so far from preventing edge-case leaks as intended,
actually introduces a memory leak in the normal error-catching path.
The leakage is easy to see if you extract the
catch_python_unique_violation() test case from plpython_error.sql
and run it in a loop, like
pl_regression=# do $$
begin
for i in 1..1000000 loop
perform catch_python_unique_violation();
end loop; end$$;
The backend's VIRT size as reported by top(1) will grow steadily.
The problem is that I did not think through the fact that
PyObject_GetAttrString() acquires a refcount on the returned object,
so that after advancing to the next frame object with
tb = PyObject_GetAttrString(tb, "tb_next");
we have an extra refcount on the new "tb" object, and there's no logic
that will get rid of that. The loop that I introduced with an eye to
cleaning things up:
/* Must release all the objects in the traceback stack */
while (tb != NULL && tb != Py_None)
{
PyObject *tb_prev = tb;
tb = PyObject_GetAttrString(tb, "tb_next");
Py_DECREF(tb_prev);
}
isn't right either, since it likewise doesn't account for the
extra refcount added by PyObject_GetAttrString.
The correct fix, I believe, is as attached. If we avoid collecting
extra refcounts during PLy_traceback(), then PLy_elog_impl() can go
back to simply doing Py_XDECREF(tb) on the first frame. Any
additional frames will go away when the previous frame object is
cleaned up and drops its refcount.
I also added a couple of comments explaining why PLy_elog_impl()
doesn't try to free the strings acquired from PLy_get_spi_error_data()
or PLy_get_error_data(). That's because I got here by looking at a
Coverity complaint about how those strings might get leaked. They
are not leaked, but in testing that I discovered this other leak.
regards, tom lane
Commits
-
Fix resource leaks in PL/Python error reporting, redux.
- fbc41a145ae0 17.7 landed
- d90c92d1c16d 13.23 landed
- cbfd4d0f883d 16.11 landed
- 7fb8c924042e 14.20 landed
- 798b19d27b28 19 (unreleased) landed
- 4cde7325924e 15.15 landed
- 447a794f6473 18.1 landed
-
Fix edge-case resource leaks in PL/Python error reporting.
- c6f7f11d8f4c 18.0 cited