Avoid-error-during-error-recovery-loops-1.patch
application/octet-stream
Filename: Avoid-error-during-error-recovery-loops-1.patch
Type: application/octet-stream
Part: 0
Patch
Format: unified
| File | + | − |
|---|---|---|
| contrib/postgres_fdw/connection.c | 29 | 10 |
diff --git a/contrib/postgres_fdw/connection.c b/contrib/postgres_fdw/connection.c
index 4931ebf591..060eac9906 100644
--- a/contrib/postgres_fdw/connection.c
+++ b/contrib/postgres_fdw/connection.c
@@ -144,7 +144,8 @@ static bool pgfdw_exec_cleanup_query_end(PGconn *conn, const char *query,
bool consume_input,
bool ignore_errors);
static bool pgfdw_get_cleanup_result(PGconn *conn, TimestampTz endtime,
- PGresult **result, bool *timed_out);
+ PGresult **result, bool *timed_out,
+ bool *internal_error);
static void pgfdw_abort_cleanup(ConnCacheEntry *entry, bool toplevel);
static bool pgfdw_abort_cleanup_begin(ConnCacheEntry *entry, bool toplevel,
List **pending_entries,
@@ -1352,6 +1353,7 @@ pgfdw_cancel_query_end(PGconn *conn, TimestampTz endtime, bool consume_input)
{
PGresult *result = NULL;
bool timed_out;
+ bool internal_error;
/*
* If requested, consume whatever data is available from the socket. (Note
@@ -1369,9 +1371,13 @@ pgfdw_cancel_query_end(PGconn *conn, TimestampTz endtime, bool consume_input)
}
/* Get and discard the result of the query. */
- if (pgfdw_get_cleanup_result(conn, endtime, &result, &timed_out))
+ if (pgfdw_get_cleanup_result(conn, endtime, &result, &timed_out,
+ &internal_error))
{
- if (timed_out)
+ if (internal_error)
+ ereport(WARNING,
+ (errmsg("could not get result of cancel request due to internal error")));
+ else if (timed_out)
ereport(WARNING,
(errmsg("could not get result of cancel request due to timeout")));
else
@@ -1442,6 +1448,7 @@ pgfdw_exec_cleanup_query_end(PGconn *conn, const char *query,
{
PGresult *result = NULL;
bool timed_out;
+ bool internal_error;
/*
* If requested, consume whatever data is available from the socket. (Note
@@ -1456,9 +1463,14 @@ pgfdw_exec_cleanup_query_end(PGconn *conn, const char *query,
}
/* Get the result of the query. */
- if (pgfdw_get_cleanup_result(conn, endtime, &result, &timed_out))
+ if (pgfdw_get_cleanup_result(conn, endtime, &result, &timed_out,
+ &internal_error))
{
- if (timed_out)
+ if (internal_error)
+ ereport(WARNING,
+ (errmsg("could not get query result due to internal error"),
+ errcontext("remote SQL command: %s", query)));
+ else if (timed_out)
ereport(WARNING,
(errmsg("could not get query result due to timeout"),
query ? errcontext("remote SQL command: %s", query) : 0));
@@ -1487,17 +1499,21 @@ pgfdw_exec_cleanup_query_end(PGconn *conn, const char *query,
*
* endtime is the time at which we should give up and assume the remote
* side is dead. Returns true if the timeout expired or connection trouble
- * occurred, false otherwise. Sets *result except in case of a timeout.
- * Sets timed_out to true only when the timeout expired.
+ * occurred, false otherwise. Sets *result except in case of a timeout or an
+ * internal error. Sets timed_out or internal_error to true only when the
+ * timeout expired or the internal error occurred.
*/
static bool
pgfdw_get_cleanup_result(PGconn *conn, TimestampTz endtime, PGresult **result,
- bool *timed_out)
+ bool *timed_out, bool *internal_error)
{
volatile bool failed = false;
PGresult *volatile last_res = NULL;
+ uint32 saveInterruptHoldoffCount = InterruptHoldoffCount;
+ MemoryContext ccxt = CurrentMemoryContext;
*timed_out = false;
+ *internal_error = false;
/* In what follows, do not leak any PGresults on an error. */
PG_TRY();
@@ -1558,8 +1574,11 @@ exit: ;
}
PG_CATCH();
{
- PQclear(last_res);
- PG_RE_THROW();
+ InterruptHoldoffCount = saveInterruptHoldoffCount;
+ MemoryContextSwitchTo(ccxt);
+ FlushErrorState();
+ *internal_error = true;
+ failed = true;
}
PG_END_TRY();