Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit bc54ef4

Browse files
committed
Fix error handling in libpqrcv_connect()
When libpqrcv_connect (also known as walrcv_connect()) failed, it leaked the libpq connection. In most paths that's fairly harmless, as the calling process will exit soon after. But e.g. CREATE SUBSCRIPTION could lead to a somewhat longer lived leak. Fix by releasing resources, including the libpq connection, on error. Add a test exercising the error code path. To make it reliable and safe, the test tries to connect to port=-1, which happens to fail during connection establishment, rather than during connection string parsing. Reviewed-by: Noah Misch <noah@leadboat.com> Discussion: https://postgr.es/m/20230121011237.q52apbvlarfv6jm6@awork3.anarazel.de Backpatch: 11-
1 parent 9567686 commit bc54ef4

File tree

3 files changed

+32
-13
lines changed

3 files changed

+32
-13
lines changed

src/backend/replication/libpqwalreceiver/libpqwalreceiver.c

+15-11
Original file line numberDiff line numberDiff line change
@@ -175,10 +175,7 @@ libpqrcv_connect(const char *conninfo, bool logical, const char *appname,
175175
conn->streamConn = PQconnectStartParams(keys, vals,
176176
/* expand_dbname = */ true);
177177
if (PQstatus(conn->streamConn) == CONNECTION_BAD)
178-
{
179-
*err = pchomp(PQerrorMessage(conn->streamConn));
180-
return NULL;
181-
}
178+
goto bad_connection_errmsg;
182179

183180
/*
184181
* Poll connection until we have OK or FAILED status.
@@ -220,10 +217,7 @@ libpqrcv_connect(const char *conninfo, bool logical, const char *appname,
220217
} while (status != PGRES_POLLING_OK && status != PGRES_POLLING_FAILED);
221218

222219
if (PQstatus(conn->streamConn) != CONNECTION_OK)
223-
{
224-
*err = pchomp(PQerrorMessage(conn->streamConn));
225-
return NULL;
226-
}
220+
goto bad_connection_errmsg;
227221

228222
if (logical)
229223
{
@@ -234,16 +228,26 @@ libpqrcv_connect(const char *conninfo, bool logical, const char *appname,
234228
if (PQresultStatus(res) != PGRES_TUPLES_OK)
235229
{
236230
PQclear(res);
237-
ereport(ERROR,
238-
(errmsg("could not clear search path: %s",
239-
pchomp(PQerrorMessage(conn->streamConn)))));
231+
*err = psprintf(_("could not clear search path: %s"),
232+
pchomp(PQerrorMessage(conn->streamConn)));
233+
goto bad_connection;
240234
}
241235
PQclear(res);
242236
}
243237

244238
conn->logical = logical;
245239

246240
return conn;
241+
242+
/* error path, using libpq's error message */
243+
bad_connection_errmsg:
244+
*err = pchomp(PQerrorMessage(conn->streamConn));
245+
246+
/* error path, error already set */
247+
bad_connection:
248+
PQfinish(conn->streamConn);
249+
pfree(conn);
250+
return NULL;
247251
}
248252

249253
/*

src/test/regress/expected/subscription.out

+9-1
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,15 @@ ALTER SUBSCRIPTION regress_testsub4 SET (origin = any);
130130

131131
DROP SUBSCRIPTION regress_testsub3;
132132
DROP SUBSCRIPTION regress_testsub4;
133-
-- fail - invalid connection string
133+
-- fail, connection string does not parse
134+
CREATE SUBSCRIPTION regress_testsub5 CONNECTION 'i_dont_exist=param' PUBLICATION testpub;
135+
ERROR: invalid connection string syntax: invalid connection option "i_dont_exist"
136+
137+
-- fail, connection string parses, but doesn't work (and does so without
138+
-- connecting, so this is reliable and safe)
139+
CREATE SUBSCRIPTION regress_testsub5 CONNECTION 'port=-1' PUBLICATION testpub;
140+
ERROR: could not connect to the publisher: invalid port number: "-1"
141+
-- fail - invalid connection string during ALTER
134142
ALTER SUBSCRIPTION regress_testsub CONNECTION 'foobar';
135143
ERROR: invalid connection string syntax: missing "=" after "foobar" in connection info string
136144

src/test/regress/sql/subscription.sql

+8-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,14 @@ ALTER SUBSCRIPTION regress_testsub4 SET (origin = any);
7777
DROP SUBSCRIPTION regress_testsub3;
7878
DROP SUBSCRIPTION regress_testsub4;
7979

80-
-- fail - invalid connection string
80+
-- fail, connection string does not parse
81+
CREATE SUBSCRIPTION regress_testsub5 CONNECTION 'i_dont_exist=param' PUBLICATION testpub;
82+
83+
-- fail, connection string parses, but doesn't work (and does so without
84+
-- connecting, so this is reliable and safe)
85+
CREATE SUBSCRIPTION regress_testsub5 CONNECTION 'port=-1' PUBLICATION testpub;
86+
87+
-- fail - invalid connection string during ALTER
8188
ALTER SUBSCRIPTION regress_testsub CONNECTION 'foobar';
8289

8390
\dRs+

0 commit comments

Comments
 (0)