Merge pull request #1764 from strk/master_connection_leaks

Fix postgresql connection leaks
This commit is contained in:
Artem Pavlenko 2013-03-28 05:49:24 -07:00
commit a20cf31c01
3 changed files with 35 additions and 14 deletions

View file

@ -143,7 +143,7 @@ public:
bool isOK() const bool isOK() const
{ {
return (PQstatus(conn_) != CONNECTION_BAD); return (!closed_) && (PQstatus(conn_) != CONNECTION_BAD);
} }
void close() void close()

View file

@ -113,10 +113,12 @@ postgis_datasource::postgis_datasource(parameters const& params)
if (pool) if (pool)
{ {
shared_ptr<Connection> conn = pool->borrowObject(); shared_ptr<Connection> conn = pool->borrowObject();
if (conn && conn->isOK()) if (!conn) return;
{
PoolGuard<shared_ptr<Connection>, PoolGuard<shared_ptr<Connection>,
shared_ptr< Pool<Connection,ConnectionCreator> > > guard(conn, pool); shared_ptr< Pool<Connection,ConnectionCreator> > > guard(conn, pool);
if (conn->isOK())
{
desc_.set_encoding(conn->client_encoding()); desc_.set_encoding(conn->client_encoding());
@ -429,6 +431,7 @@ postgis_datasource::~postgis_datasource()
if (conn) if (conn)
{ {
conn->close(); conn->close();
pool->returnObject(conn);
} }
} }
} }
@ -693,6 +696,7 @@ featureset_ptr postgis_datasource::features(const query& q) const
if (conn) if (conn)
{ {
err_msg += conn->status(); err_msg += conn->status();
pool->returnObject(conn);
} }
else else
{ {
@ -714,10 +718,11 @@ featureset_ptr postgis_datasource::features_at_point(coord2d const& pt, double t
if (pool) if (pool)
{ {
shared_ptr<Connection> conn = pool->borrowObject(); shared_ptr<Connection> conn = pool->borrowObject();
if (conn && conn->isOK()) if (!conn) return featureset_ptr();
{
PoolGuard<shared_ptr<Connection>, shared_ptr< Pool<Connection,ConnectionCreator> > > guard(conn, pool); PoolGuard<shared_ptr<Connection>, shared_ptr< Pool<Connection,ConnectionCreator> > > guard(conn, pool);
if (conn->isOK())
{
if (geometryColumn_.empty()) if (geometryColumn_.empty())
{ {
std::ostringstream s_error; std::ostringstream s_error;
@ -798,10 +803,10 @@ box2d<double> postgis_datasource::envelope() const
if (pool) if (pool)
{ {
shared_ptr<Connection> conn = pool->borrowObject(); shared_ptr<Connection> conn = pool->borrowObject();
if (conn && conn->isOK()) if (!conn) return extent_;
{
PoolGuard<shared_ptr<Connection>, shared_ptr< Pool<Connection,ConnectionCreator> > > guard(conn, pool); PoolGuard<shared_ptr<Connection>, shared_ptr< Pool<Connection,ConnectionCreator> > > guard(conn, pool);
if (conn->isOK())
{
std::ostringstream s; std::ostringstream s;
if (geometryColumn_.empty()) if (geometryColumn_.empty())
@ -890,10 +895,10 @@ boost::optional<mapnik::datasource::geometry_t> postgis_datasource::get_geometry
if (pool) if (pool)
{ {
shared_ptr<Connection> conn = pool->borrowObject(); shared_ptr<Connection> conn = pool->borrowObject();
if (conn && conn->isOK()) if (!conn) return result;
{
PoolGuard<shared_ptr<Connection>, shared_ptr< Pool<Connection,ConnectionCreator> > > guard(conn, pool); PoolGuard<shared_ptr<Connection>, shared_ptr< Pool<Connection,ConnectionCreator> > > guard(conn, pool);
if (conn->isOK())
{
std::ostringstream s; std::ostringstream s;
std::string g_type; std::string g_type;
try try

View file

@ -495,6 +495,22 @@ if 'postgis' in mapnik.DatasourceCache.plugin_names() \
eq_(feat['gid'],2) eq_(feat['gid'],2)
eq_(feat['int_field'],922337203685477580) eq_(feat['int_field'],922337203685477580)
def test_persist_connection_off():
# NOTE: max_size should be equal or greater than
# the pool size. There's currently no API to
# check nor set that size, but the current
# default is 20, so we use that value. See
# http://github.com/mapnik/mapnik/issues/863
max_size = 20
for i in range(0, max_size+1):
ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME,
max_size=1, # unused
persist_connection=False,
table='(select ST_MakePoint(0,0) as g, pg_backend_pid() as p, 1 as v) as w',
geometry_field='g')
fs = ds.featureset()
eq_(fs.next()['v'], 1)
atexit.register(postgis_takedown) atexit.register(postgis_takedown)
if __name__ == "__main__": if __name__ == "__main__":