Skip to content

Commit e460248

Browse files
committed
dblink, postgres_fdw: Handle interrupts during connection establishment
Until now dblink and postgres_fdw did not process interrupts during connection establishment. Besides preventing query cancellations etc, this can lead to undetected deadlocks, as global barriers are not processed. These aforementioned undetected deadlocks are the reason for the spate of CI test failures in the FreeBSD 'test_running' step. Fix the bug by using the helper from libpq-be-fe-helpers.h, introduced in a prior commit. Besides fixing the bug, this also removes duplicated code around reserving file descriptors. As the change is relatively large and there are no field reports of the problem, don't backpatch for now. Reviewed-by: Thomas Munro <thomas.munro@gmail.com> Discussion: https://postgr.es/m/20220925232237.p6uskba2dw6fnwj2@awork3.anarazel.de Backpatch:
1 parent 28a5917 commit e460248

File tree

2 files changed

+17
-104
lines changed

2 files changed

+17
-104
lines changed

contrib/dblink/dblink.c

Lines changed: 11 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
#include "funcapi.h"
4949
#include "lib/stringinfo.h"
5050
#include "libpq-fe.h"
51+
#include "libpq/libpq-be-fe-helpers.h"
5152
#include "mb/pg_wchar.h"
5253
#include "miscadmin.h"
5354
#include "parser/scansup.h"
@@ -199,37 +200,14 @@ dblink_get_conn(char *conname_or_str,
199200
connstr = conname_or_str;
200201
dblink_connstr_check(connstr);
201202

202-
/*
203-
* We must obey fd.c's limit on non-virtual file descriptors. Assume
204-
* that a PGconn represents one long-lived FD. (Doing this here also
205-
* ensures that VFDs are closed if needed to make room.)
206-
*/
207-
if (!AcquireExternalFD())
208-
{
209-
#ifndef WIN32 /* can't write #if within ereport() macro */
210-
ereport(ERROR,
211-
(errcode(ERRCODE_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION),
212-
errmsg("could not establish connection"),
213-
errdetail("There are too many open files on the local server."),
214-
errhint("Raise the server's max_files_per_process and/or \"ulimit -n\" limits.")));
215-
#else
216-
ereport(ERROR,
217-
(errcode(ERRCODE_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION),
218-
errmsg("could not establish connection"),
219-
errdetail("There are too many open files on the local server."),
220-
errhint("Raise the server's max_files_per_process setting.")));
221-
#endif
222-
}
223-
224203
/* OK to make connection */
225-
conn = PQconnectdb(connstr);
204+
conn = libpqsrv_connect(connstr, PG_WAIT_EXTENSION);
226205

227206
if (PQstatus(conn) == CONNECTION_BAD)
228207
{
229208
char *msg = pchomp(PQerrorMessage(conn));
230209

231-
PQfinish(conn);
232-
ReleaseExternalFD();
210+
libpqsrv_disconnect(conn);
233211
ereport(ERROR,
234212
(errcode(ERRCODE_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION),
235213
errmsg("could not establish connection"),
@@ -312,36 +290,13 @@ dblink_connect(PG_FUNCTION_ARGS)
312290
/* check password in connection string if not superuser */
313291
dblink_connstr_check(connstr);
314292

315-
/*
316-
* We must obey fd.c's limit on non-virtual file descriptors. Assume that
317-
* a PGconn represents one long-lived FD. (Doing this here also ensures
318-
* that VFDs are closed if needed to make room.)
319-
*/
320-
if (!AcquireExternalFD())
321-
{
322-
#ifndef WIN32 /* can't write #if within ereport() macro */
323-
ereport(ERROR,
324-
(errcode(ERRCODE_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION),
325-
errmsg("could not establish connection"),
326-
errdetail("There are too many open files on the local server."),
327-
errhint("Raise the server's max_files_per_process and/or \"ulimit -n\" limits.")));
328-
#else
329-
ereport(ERROR,
330-
(errcode(ERRCODE_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION),
331-
errmsg("could not establish connection"),
332-
errdetail("There are too many open files on the local server."),
333-
errhint("Raise the server's max_files_per_process setting.")));
334-
#endif
335-
}
336-
337293
/* OK to make connection */
338-
conn = PQconnectdb(connstr);
294+
conn = libpqsrv_connect(connstr, PG_WAIT_EXTENSION);
339295

340296
if (PQstatus(conn) == CONNECTION_BAD)
341297
{
342298
msg = pchomp(PQerrorMessage(conn));
343-
PQfinish(conn);
344-
ReleaseExternalFD();
299+
libpqsrv_disconnect(conn);
345300
if (rconn)
346301
pfree(rconn);
347302

@@ -366,10 +321,7 @@ dblink_connect(PG_FUNCTION_ARGS)
366321
else
367322
{
368323
if (pconn->conn)
369-
{
370-
PQfinish(pconn->conn);
371-
ReleaseExternalFD();
372-
}
324+
libpqsrv_disconnect(conn);
373325
pconn->conn = conn;
374326
}
375327

@@ -402,8 +354,7 @@ dblink_disconnect(PG_FUNCTION_ARGS)
402354
if (!conn)
403355
dblink_conn_not_avail(conname);
404356

405-
PQfinish(conn);
406-
ReleaseExternalFD();
357+
libpqsrv_disconnect(conn);
407358
if (rconn)
408359
{
409360
deleteConnection(conname);
@@ -838,10 +789,7 @@ dblink_record_internal(FunctionCallInfo fcinfo, bool is_async)
838789
{
839790
/* if needed, close the connection to the database */
840791
if (freeconn)
841-
{
842-
PQfinish(conn);
843-
ReleaseExternalFD();
844-
}
792+
libpqsrv_disconnect(conn);
845793
}
846794
PG_END_TRY();
847795

@@ -1516,10 +1464,7 @@ dblink_exec(PG_FUNCTION_ARGS)
15161464
{
15171465
/* if needed, close the connection to the database */
15181466
if (freeconn)
1519-
{
1520-
PQfinish(conn);
1521-
ReleaseExternalFD();
1522-
}
1467+
libpqsrv_disconnect(conn);
15231468
}
15241469
PG_END_TRY();
15251470

@@ -2606,8 +2551,7 @@ createNewConnection(const char *name, remoteConn *rconn)
26062551

26072552
if (found)
26082553
{
2609-
PQfinish(rconn->conn);
2610-
ReleaseExternalFD();
2554+
libpqsrv_disconnect(rconn->conn);
26112555
pfree(rconn);
26122556

26132557
ereport(ERROR,
@@ -2647,8 +2591,7 @@ dblink_security_check(PGconn *conn, remoteConn *rconn)
26472591
{
26482592
if (!PQconnectionUsedPassword(conn))
26492593
{
2650-
PQfinish(conn);
2651-
ReleaseExternalFD();
2594+
libpqsrv_disconnect(conn);
26522595
if (rconn)
26532596
pfree(rconn);
26542597

contrib/postgres_fdw/connection.c

Lines changed: 6 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "catalog/pg_user_mapping.h"
1818
#include "commands/defrem.h"
1919
#include "funcapi.h"
20+
#include "libpq/libpq-be-fe-helpers.h"
2021
#include "mb/pg_wchar.h"
2122
#include "miscadmin.h"
2223
#include "pgstat.h"
@@ -446,35 +447,10 @@ connect_pg_server(ForeignServer *server, UserMapping *user)
446447
/* verify the set of connection parameters */
447448
check_conn_params(keywords, values, user);
448449

449-
/*
450-
* We must obey fd.c's limit on non-virtual file descriptors. Assume
451-
* that a PGconn represents one long-lived FD. (Doing this here also
452-
* ensures that VFDs are closed if needed to make room.)
453-
*/
454-
if (!AcquireExternalFD())
455-
{
456-
#ifndef WIN32 /* can't write #if within ereport() macro */
457-
ereport(ERROR,
458-
(errcode(ERRCODE_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION),
459-
errmsg("could not connect to server \"%s\"",
460-
server->servername),
461-
errdetail("There are too many open files on the local server."),
462-
errhint("Raise the server's max_files_per_process and/or \"ulimit -n\" limits.")));
463-
#else
464-
ereport(ERROR,
465-
(errcode(ERRCODE_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION),
466-
errmsg("could not connect to server \"%s\"",
467-
server->servername),
468-
errdetail("There are too many open files on the local server."),
469-
errhint("Raise the server's max_files_per_process setting.")));
470-
#endif
471-
}
472-
473450
/* OK to make connection */
474-
conn = PQconnectdbParams(keywords, values, false);
475-
476-
if (!conn)
477-
ReleaseExternalFD(); /* because the PG_CATCH block won't */
451+
conn = libpqsrv_connect_params(keywords, values,
452+
/* expand_dbname = */ false,
453+
PG_WAIT_EXTENSION);
478454

479455
if (!conn || PQstatus(conn) != CONNECTION_OK)
480456
ereport(ERROR,
@@ -507,12 +483,7 @@ connect_pg_server(ForeignServer *server, UserMapping *user)
507483
}
508484
PG_CATCH();
509485
{
510-
/* Release PGconn data structure if we managed to create one */
511-
if (conn)
512-
{
513-
PQfinish(conn);
514-
ReleaseExternalFD();
515-
}
486+
libpqsrv_disconnect(conn);
516487
PG_RE_THROW();
517488
}
518489
PG_END_TRY();
@@ -528,9 +499,8 @@ disconnect_pg_server(ConnCacheEntry *entry)
528499
{
529500
if (entry->conn != NULL)
530501
{
531-
PQfinish(entry->conn);
502+
libpqsrv_disconnect(entry->conn);
532503
entry->conn = NULL;
533-
ReleaseExternalFD();
534504
}
535505
}
536506

0 commit comments

Comments
 (0)