0002-Idle-transaction-cancellation.patch
text/x-patch
Filename: 0002-Idle-transaction-cancellation.patch
Type: text/x-patch
Part: 1
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch 0002
Subject: Idle transaction cancellation.
| File | + | − |
|---|---|---|
| src/backend/tcop/postgres.c | 55 | 20 |
From 6a27a19395df053112616b83c966f4b20869ebc3 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Fri, 21 May 2010 20:17:11 +0200
Subject: [PATCH 2/2] Idle transaction cancellation.
---
src/backend/tcop/postgres.c | 75 +++++++++++++++++++++++++++++++-----------
1 files changed, 55 insertions(+), 20 deletions(-)
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index cba90a9..d0c8696 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -177,6 +177,12 @@ static bool RecoveryConflictPending = false;
static bool RecoveryConflictRetryable = true;
static ProcSignalReason RecoveryConflictReason;
+/*
+ * Are we disallowed from sending a "ready for query" message right
+ * now because it would confuse the frontend?
+ */
+bool silent_error_while_idle = false;
+
/* ----------------------------------------------------------------
* decls for routines only used in this file
* ----------------------------------------------------------------
@@ -2877,6 +2883,8 @@ RecoveryConflictInterrupt(ProcSignalReason reason)
void
ProcessInterrupts(void)
{
+ int error = ERROR;
+
/* OK to accept interrupt now? */
if (InterruptHoldoffCount != 0 || CritSectionCount != 0)
return;
@@ -2949,18 +2957,24 @@ ProcessInterrupts(void)
RecoveryConflictPending = false;
DisableNotifyInterrupt();
DisableCatchupInterrupt();
- if (DoingCommandRead)
- ereport(FATAL,
- (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
- errmsg("terminating connection due to conflict with recovery"),
- errdetail_recovery_conflict(),
- errhint("In a moment you should be able to reconnect to the"
- " database and repeat your command.")));
- else
- ereport(ERROR,
- (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
- errmsg("canceling statement due to conflict with recovery"),
- errdetail_recovery_conflict()));
+
+ if (DoingCommandRead){
+ /*
+ * We cant issue a normal ERROR here because the
+ * client doesnt expect the server to send an error at
+ * that point.
+ * We also may not send a "ready for query"/Z message
+ * because that would be unexpected as well.
+ */
+ silent_error_while_idle = true;
+ error |= LOG_NO_CLIENT;
+
+ }
+
+ ereport(error,
+ (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
+ errmsg("canceling statement due to conflict with recovery"),
+ errdetail_recovery_conflict()));
}
/*
@@ -2968,15 +2982,18 @@ ProcessInterrupts(void)
* request --- sending an extra error message won't accomplish
* anything. Otherwise, go ahead and throw the error.
*/
- if (!DoingCommandRead)
+ if (DoingCommandRead)
{
- ImmediateInterruptOK = false; /* not idle anymore */
- DisableNotifyInterrupt();
- DisableCatchupInterrupt();
- ereport(ERROR,
- (errcode(ERRCODE_QUERY_CANCELED),
- errmsg("canceling statement due to user request")));
+ silent_error_while_idle = true;
+ error |= LOG_NO_CLIENT;
}
+
+ ImmediateInterruptOK = false; /* not idle anymore */
+ DisableNotifyInterrupt();
+ DisableCatchupInterrupt();
+ ereport(error,
+ (errcode(ERRCODE_QUERY_CANCELED),
+ errmsg("canceling statement due to user request")));
}
/* If we get here, do nothing (probably, QueryCancelPending was reset) */
}
@@ -3794,7 +3811,7 @@ PostgresMain(int argc, char *argv[], const char *username)
* uncommitted updates (that confuses autovacuum). The notification
* processor wants a call too, if we are not in a transaction block.
*/
- if (send_ready_for_query)
+ if (send_ready_for_query && !silent_error_while_idle)
{
if (IsAbortedTransactionBlockState())
{
@@ -3819,6 +3836,7 @@ PostgresMain(int argc, char *argv[], const char *username)
send_ready_for_query = false;
}
+
/*
* (2) Allow asynchronous signals to be executed immediately if they
* come in while we are waiting for client input. (This must be
@@ -3854,6 +3872,23 @@ PostgresMain(int argc, char *argv[], const char *username)
if (ignore_till_sync && firstchar != EOF)
continue;
+ if(silent_error_while_idle && !doing_extended_query_message)
+ {
+ /*
+ * When using the simple protocol:
+ * At this point we have processed a ReadCommand which means
+ * that we got some input from the frontend and thus can start
+ * spewing errors again
+
+ * When using the extended protocol:
+ * doing_extended_query_message is false after a 'sync'
+ * message - which is exactly the point after which we can
+ * start sending errors again.
+ */
+ silent_error_while_idle = false;
+ }
+
+
switch (firstchar)
{
case 'Q': /* simple query */
--
1.7.3.rc1.5.g73aa2