Snapshot leak warning with lo_export in subtransaction

From: Heikki Linnakangas <hlinnaka(at)iki(dot)fi>
To: Pg Bugs <pgsql-bugs(at)postgresql(dot)org>
Cc: Andrew B <pgsql(dot)20(dot)drkshadow(at)spamgourmet(dot)com>
Subject: Snapshot leak warning with lo_export in subtransaction
Date: 2021-09-27 10:55:00
Message-ID: 32bf767a-2d65-71c4-f170-122f416bab7e@iki.fi
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-bugs

Hi,

Andrew B reported this warning off-list:

postgres=# SELECT lo_create(41174);
lo_create
-----------
41174
(1 row)

postgres=# DO $$
BEGIN
PERFORM lo_export(41174, '/invalid/path');
EXCEPTION
WHEN others THEN RAISE NOTICE 'error: %', sqlerrm;
END;
$$;
NOTICE: error: could not create server file "/invalid/path": No such
file or directory
WARNING: Snapshot reference leak: Snapshot 0x5634afd61cb8 still referenced
DO

The code in be_lo_export does this:

>
> CreateFSContext();
>
> /*
> * open the inversion object (no need to test for failure)
> */
> lobj = inv_open(lobjId, INV_READ, fscxt);
>
> /*
> * open the file to be written to
> *
> ...

And inv_open does this:

> /* OK to create a descriptor */
> retval = (LargeObjectDesc *) MemoryContextAlloc(mcxt,
> sizeof(LargeObjectDesc));
> retval->id = lobjId;
> retval->subid = GetCurrentSubTransactionId();
> retval->offset = 0;
> retval->flags = descflags;
>
> /*
> * We must register the snapshot in TopTransaction's resowner, because it
> * must stay alive until the LO is closed rather than until the current
> * portal shuts down. Do this last to avoid uselessly leaking the
> * snapshot if an error is thrown above.
> */
> if (snapshot)
> snapshot = RegisterSnapshotOnOwner(snapshot,
> TopTransactionResourceOwner);
> retval->snapshot = snapshot;

So this is pretty clear-cut: if opening the file fails, the snapshot
reference is leaked in TopTransactionResourceOwner. Similarly, the
LargeObjectDesc is leaked in 'fscxt', which is a subcontext of
TopMemoryContext, but that doesn't generate a warning.

I propose the attached patch to fix that. With the patch, we use
CurrentMemoryContext and no resource owner for transient
LargeObjectDescs that are opened and closed in the same function call.

This should be backpatched to all supported versions. This adds an
argument to 'inv_open' function, but I don't think there are extensions
that use the inv_*() functions directly. inv_api.c relies on
close_lo_relation() being called at the end of transaction, so I think
an extension would find it hard to use those functions correctly, anyway.

- Heikki

Attachment Content-Type Size
0001-Fix-snapshot-reference-leak-if-lo_export-fails.patch text/x-patch 12.4 KB

Responses

Browse pgsql-bugs by date

  From Date Subject
Next Message Alvaro Herrera 2021-09-27 12:33:23 Re: Snapshot leak warning with lo_export in subtransaction
Previous Message Etsuro Fujita 2021-09-26 08:56:57 Re: BUG #16583: merge join on tables with different DB collation behind postgres_fdw fails