* ProcessInterrupts: out-of-line portion of CHECK_FOR_INTERRUPTS() macro * * If an interrupt condition is pending, and it's safe to service it, * then clear the flag and accept the interrupt. Called only when * InterruptPending is true. * * Note: if INTERRUPTS_CAN_BE_PROCESSED() is true, then ProcessInterrupts * is guaranteed to clear the InterruptPending flag before returning. * (This is
| 4061 | * ProcessInterrupts was invoked, respectively. |
| 4062 | */ |
| 4063 | void |
| 4064 | ProcessInterrupts(const char* filename, int lineno) |
| 4065 | { |
| 4066 | /* OK to accept any interrupts now? */ |
| 4067 | if (InterruptHoldoffCount != 0 || CritSectionCount != 0) |
| 4068 | return; |
| 4069 | InterruptPending = false; |
| 4070 | |
| 4071 | if (ProcDiePending) |
| 4072 | { |
| 4073 | ProcDiePending = false; |
| 4074 | QueryCancelPending = false; /* ProcDie trumps QueryCancel */ |
| 4075 | LockErrorCleanup(); |
| 4076 | /* As in quickdie, don't risk sending to client during auth */ |
| 4077 | if (ClientAuthInProgress && whereToSendOutput == DestRemote) |
| 4078 | whereToSendOutput = DestNone; |
| 4079 | if (ClientAuthInProgress) |
| 4080 | ereport(FATAL, |
| 4081 | (errcode(ERRCODE_QUERY_CANCELED), |
| 4082 | errmsg("canceling authentication due to timeout"))); |
| 4083 | else if (IsAutoVacuumWorkerProcess()) |
| 4084 | ereport(FATAL, |
| 4085 | (errcode(ERRCODE_ADMIN_SHUTDOWN), |
| 4086 | errmsg("terminating autovacuum process due to administrator command"))); |
| 4087 | else if (IsLogicalWorker()) |
| 4088 | ereport(FATAL, |
| 4089 | (errcode(ERRCODE_ADMIN_SHUTDOWN), |
| 4090 | errmsg("terminating logical replication worker due to administrator command"))); |
| 4091 | else if (IsLogicalLauncher()) |
| 4092 | { |
| 4093 | ereport(DEBUG1, |
| 4094 | (errmsg_internal("logical replication launcher shutting down"))); |
| 4095 | |
| 4096 | /* |
| 4097 | * The logical replication launcher can be stopped at any time. |
| 4098 | * Use exit status 1 so the background worker is restarted. |
| 4099 | */ |
| 4100 | proc_exit(1); |
| 4101 | } |
| 4102 | else if (RecoveryConflictPending && RecoveryConflictRetryable) |
| 4103 | { |
| 4104 | pgstat_report_recovery_conflict(RecoveryConflictReason); |
| 4105 | ereport(FATAL, |
| 4106 | (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE), |
| 4107 | errmsg("terminating connection due to conflict with recovery"), |
| 4108 | errdetail_recovery_conflict())); |
| 4109 | } |
| 4110 | else if (RecoveryConflictPending) |
| 4111 | { |
| 4112 | /* Currently there is only one non-retryable recovery conflict */ |
| 4113 | Assert(RecoveryConflictReason == PROCSIG_RECOVERY_CONFLICT_DATABASE); |
| 4114 | pgstat_report_recovery_conflict(RecoveryConflictReason); |
| 4115 | ereport(FATAL, |
| 4116 | (errcode(ERRCODE_DATABASE_DROPPED), |
| 4117 | errmsg("terminating connection due to conflict with recovery"), |
| 4118 | errdetail_recovery_conflict())); |
| 4119 | } |
| 4120 | else if (IsBackgroundWorker) |