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?
+ */
+static bool silent_error_while_idle = false;
+
/* ----------------------------------------------------------------
* decls for routines only used in this file
* ----------------------------------------------------------------
void
ProcessInterrupts(void)
{
+ int error = ERROR;
+
/* OK to accept interrupt now? */
if (InterruptHoldoffCount != 0 || CritSectionCount != 0)
return;
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()));
}
/*
* 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) */
}
set_ps_display("idle", false);
pgstat_report_activity("<IDLE>");
}
-
- ReadyForQuery(whereToSendOutput);
- send_ready_for_query = false;
+ if(!silent_error_while_idle){
+ ReadyForQuery(whereToSendOutput);
+ 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
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 */