| From: | Matt Carter <Matt(dot)Carter(at)twosigma(dot)com> |
|---|---|
| To: | Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us> |
| Cc: | Andres Freund <andres(at)anarazel(dot)de>, "pgsql-bugs(at)lists(dot)postgresql(dot)org" <pgsql-bugs(at)lists(dot)postgresql(dot)org> |
| Subject: | RE: BUG #19411: libpq 16.x exhibits a memory leak when connections are repeatedly created and destroyed |
| Date: | 2026-10-29 21:52:17 |
| Message-ID: | BL3PR08MB728371A661250E2282D5FD0E996E2@BL3PR08MB7283.namprd08.prod.outlook.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-bugs |
> Tom Lane wrote:
>> I propose changing its name altogether, as attached.
Thanks, Tom. I tested your patch against my GSSAPI-authenticated server (MIT krb5 1.20.1, OpenSSL 1.1). It applies to 18.3 with line offsets and builds without warnings. Using the reproducer from my previous message, these are the bytes per connection still allocated after warm-up (450 connections):
18.3 unpatched 17844
18.3 + your patch 108
18.3 + your patch, gssencmode=disable 42
GSSAPI authentication works as before. Under gdb, every gss_acquire_cred() now has a matching gss_release_cred():
- With gssencmode=disable there is one acquire per connection. Both gss_init_sec_context() calls share it, and pqDropConnection() releases it.
- With the default gssencmode, pqsecure_open_gss() releases the encryption probe's credential before the fallback. Authentication then acquires one more, and pqDropConnection() releases that.
I couldn't exercise gssencmode=require past negotiation, because my server's pg_hba.conf rejects GSSAPI-encrypted connections. It fails the same way with and without the patch.
We would benefit from back-patches to 16 and 17:
- Our Airflow deployments get libpq 17.11 from psycopg2-binary 2.9.13, which measures 17930 bytes/connection with the same reproducer.
- Our internal builds ship 16.x. There the fe-connect.c hunks won't apply as-is, but the pg_GSS_continue() change alone takes 16.7 from 17823 to 123 bytes per connection.
Matt
________________________________________
From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Sent: Thursday, 29 October 2026 20:47:18
To: Matt Carter
Cc: Andres Freund; pgsql-bugs(at)lists(dot)postgresql(dot)org
Subject: Re: BUG #19411: libpq 16.x exhibits a memory leak when connections are repeatedly created and destroyed
Matt Carter <Matt(dot)Carter(at)twosigma(dot)com> writes:
> Your suspicion was right, and I'm sorry for pointing at psycopg2 earlier. The leak is in libpq, and it needs GSSAPI *authentication*. Every connection to my server authenticates via "gss" in pg_hba.conf. My gssencmode=disable runs only turned off GSS encryption, so none of my tests ever removed it.
> pg_GSS_continue() runs once per GSS round trip, and Kerberos with mutual authentication takes two. On every call it does
> /* Only try to acquire credentials if GSS delegation isn't disabled. */
> if (!pg_GSS_have_cred_cache(&conn->gcred))
> conn->gcred = GSS_C_NO_CREDENTIAL;
> pg_GSS_have_cred_cache() calls gss_acquire_cred() and stores the result in *cred_out. It doesn't release the credential that is already there.
Ooops. It looks like this isn't the only place that makes that
mistake: select_next_encryption_method seems at risk too, or at least
if it's not, that's because of caller logic not anything it's doing
itself. I think that's partially because pg_GSS_have_cred_cache is
poorly named: it sounds like a status test not an action, and its API
is just bizarre. I propose changing its name altogether, as attached.
regards, tom lane
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Tom Lane | 2026-10-29 21:54:21 | Re: postgres_fdw returns wrong rows for age(timestamptz, timestamptz) filters |
| Previous Message | Laurenz Albe | 2026-10-29 21:40:24 | Re: postgres_fdw returns wrong rows for age(timestamptz, timestamptz) filters |