Thread: Exporting closePGconn from libpq

Exporting closePGconn from libpq

From
Leon Smith
Date:
A minor issue has come up in creating low-level bindings to libpq for
safe garbage-collected languages,  namely that PQfinish is the only
(AFAICT) way to close a connection but also de-allocates the memory
used to represent the database connection.    It would be preferable
to call PQfinish to free the memory in a finalizer,  but appilcations
need a way to disconnect from the database at a predictable and
deterministic point in time,  whereas leaving a bit of memory around
until the GC finally gets to it is relatively harmless.    The
low-level binding has a couple of options:

1.  Ignore the issue and allow for the possibility of a segfault if
the library is used incorrectly,  which is not a good situation for
"safe" languages.

2.  Create a wrapper that tracks whether or not PQfinish has ever been
called,  so that attempts to use a connection afterwards can be turned
into native exceptions/other forms of error signaling.  This kind of
solution can introduce their own minor issues.

3.  Hack libpq to export closePGconn so that libpq can safely signal
the low-level bindings of the error when a connection is used after it
is disconnected,  reserving PQfinish to run in a GC-triggered
finalizer.  While this is a technically preferable solution,  without
getting the change into upstream sources it is also a deployment
nightmare.

Is there any particular reason why closePGconn should not be exported
from libpq?

Best,
Leon


Re: Exporting closePGconn from libpq

From
Tom Lane
Date:
Leon Smith <leon.p.smith@gmail.com> writes:
> ... The low-level binding has a couple of options:

> 1.  Ignore the issue and allow for the possibility of a segfault if
> the library is used incorrectly,  which is not a good situation for
> "safe" languages.

> 2.  Create a wrapper that tracks whether or not PQfinish has ever been
> called,  so that attempts to use a connection afterwards can be turned
> into native exceptions/other forms of error signaling.  This kind of
> solution can introduce their own minor issues.

> 3.  Hack libpq to export closePGconn so that libpq can safely signal
> the low-level bindings of the error when a connection is used after it
> is disconnected,  reserving PQfinish to run in a GC-triggered
> finalizer.  While this is a technically preferable solution,  without
> getting the change into upstream sources it is also a deployment
> nightmare.

> Is there any particular reason why closePGconn should not be exported
> from libpq?

Yes: it'd introduce a new externally-visible state that libpq now has to
worry about supporting in all its operations, ie connection closed but
not gone.  This state is guaranteed to be poorly tested and hence buggy.

I think you need a wrapper object.  Given the context you're describing,
I'd be willing to lay a side bet that you'll end up needing a wrapper
anyway, even if it seems like you could avoid it right now.  Language
embeddings of libpq tend to accrete features...
        regards, tom lane


Re: Exporting closePGconn from libpq

From
Leon Smith
Date:
On Sat, May 14, 2011 at 11:37 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> Yes: it'd introduce a new externally-visible state that libpq now has to
> worry about supporting in all its operations, ie connection closed but
> not gone.  This state is guaranteed to be poorly tested and hence buggy.

If you connect to a database over an unreliable network,  you can lose
the connection without warning at any time.  Thus libpq must already
support a "connection 'closed' but not gone" state,  and I'm fine with
making the "explicitly disconnected" state indistinguishable from the
"connection lost" state.

> I think you need a wrapper object.  Given the context you're describing,
> I'd be willing to lay a side bet that you'll end up needing a wrapper
> anyway, even if it seems like you could avoid it right now.  Language
> embeddings of libpq tend to accrete features...

The intention of the low-level bindings I'm working on is to keep
features to an absolute minimum; to bind calls to C in a 1-1 fashion
and to handle memory management and error signaling associated with
foreign calls.  Of course such a library is not intended to be
particularly attractive for application development,  but rather as a
library that can be wrapped up into a higher-level database access
library that's free to accrete features.  :)

Best,
Leon


Re: Exporting closePGconn from libpq

From
Markus Wanner
Date:
Leon,

On 05/14/2011 05:23 PM, Leon Smith wrote:
> A minor issue has come up in creating low-level bindings to libpq for
> safe garbage-collected languages,  namely that PQfinish is the only
> (AFAICT) way to close a connection but also de-allocates the memory
> used to represent the database connection.    It would be preferable
> to call PQfinish to free the memory in a finalizer,  but appilcations
> need a way to disconnect from the database at a predictable and
> deterministic point in time,  whereas leaving a bit of memory around
> until the GC finally gets to it is relatively harmless.

It's harmless, but I think it's also useless.  Or why do you want to
keep that (libpq-private) bit of memory around beyond PQfinish()?

I'm not sure what language or VM you have in mind, but your description
sounds like you are writing a wrapper by definition.

Regards

Markus Wanner


Re: Exporting closePGconn from libpq

From
Merlin Moncure
Date:
On Sat, May 14, 2011 at 11:23 AM, Leon Smith <leon.p.smith@gmail.com> wrote:
> A minor issue has come up in creating low-level bindings to libpq for
> safe garbage-collected languages,  namely that PQfinish is the only
> (AFAICT) way to close a connection but also de-allocates the memory
> used to represent the database connection.    It would be preferable
> to call PQfinish to free the memory in a finalizer,  but appilcations
> need a way to disconnect from the database at a predictable and
> deterministic point in time,  whereas leaving a bit of memory around
> until the GC finally gets to it is relatively harmless.    The
> low-level binding has a couple of options:
>
> 1.  Ignore the issue and allow for the possibility of a segfault if
> the library is used incorrectly,  which is not a good situation for
> "safe" languages.

The 'safety' of the language has nothing to do with it. It should
possible to maintain state outside of libpq without crashing.  Which
language by the way?

> 2.  Create a wrapper that tracks whether or not PQfinish has ever been
> called,  so that attempts to use a connection afterwards can be turned
> into native exceptions/other forms of error signaling.  This kind of
> solution can introduce their own minor issues.

This is probably your answer.

> 3.  Hack libpq to export closePGconn so that libpq can safely signal
> the low-level bindings of the error when a connection is used after it
> is disconnected,  reserving PQfinish to run in a GC-triggered
> finalizer.  While this is a technically preferable solution,  without
> getting the change into upstream sources it is also a deployment
> nightmare.

This is not going to be as helpful as you think -- in many cases the
connection will not go 'bad' until you attempt to use...libpq runs in
thread and does no management when you are not inside a libpq call.
Your hypothetical callback would only get fired when you are making a
libpq call anyways and you haven't made a case why you can't just wrap
the query call with a a post call check to connection status.

merlin