Exporting closePGconn from libpq

Started by Leon Smithover 14 years ago5 messages
#1Leon Smith
leon.p.smith@gmail.com

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

#2Tom Lane
tgl@sss.pgh.pa.us
In reply to: Leon Smith (#1)
Re: Exporting closePGconn from libpq

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

#3Leon Smith
leon.p.smith@gmail.com
In reply to: Tom Lane (#2)
Re: Exporting closePGconn from libpq

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

#4Markus Wanner
markus@bluegap.ch
In reply to: Leon Smith (#1)
Re: Exporting closePGconn from libpq

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

#5Merlin Moncure
mmoncure@gmail.com
In reply to: Leon Smith (#1)
Re: Exporting closePGconn from libpq

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