*** a/src/backend/replication/syncrep.c --- b/src/backend/replication/syncrep.c *************** *** 63,71 **** /* User-settable parameters for sync rep */ bool sync_rep_mode = false; /* Only set in user backends */ ! int sync_rep_timeout = 120; /* Only set in user backends */ char *SyncRepStandbyNames; #define IsOnSyncRepQueue() (MyProc->lwWaiting) --- 63,72 ---- /* User-settable parameters for sync rep */ bool sync_rep_mode = false; /* Only set in user backends */ ! int sync_rep_timeout = 120; /* Only set in user backends */ char *SyncRepStandbyNames; + bool WaitingForSyncRep = false; /* Global state for some exit methods */ #define IsOnSyncRepQueue() (MyProc->lwWaiting) *************** *** 202,207 **** SyncRepWaitOnQueue(XLogRecPtr XactCommitLSN) --- 203,209 ---- MyProc->waitLSN = XactCommitLSN; SyncRepAddToQueue(); LWLockRelease(SyncRepLock); + WaitingForSyncRep = true; /* * Alter ps display to show waiting for sync rep. *************** *** 241,246 **** SyncRepWaitOnQueue(XLogRecPtr XactCommitLSN) --- 243,249 ---- { SyncRepRemoveFromQueue(); LWLockRelease(SyncRepLock); + WaitingForSyncRep = false; /* * Reset our waitLSN. *************** *** 248,254 **** SyncRepWaitOnQueue(XLogRecPtr XactCommitLSN) MyProc->waitLSN.xlogid = 0; MyProc->waitLSN.xrecoff = 0; - if (new_status) { /* Reset ps display */ --- 251,256 ---- *** a/src/backend/tcop/postgres.c --- b/src/backend/tcop/postgres.c *************** *** 2902,2907 **** ProcessInterrupts(void) --- 2902,2935 ---- ereport(FATAL, (errcode(ERRCODE_ADMIN_SHUTDOWN), errmsg("terminating autovacuum process due to administrator command"))); + else if (WaitingForSyncRep) + { + /* + * This must NOT be a FATAL message. We want the state of the + * transaction being aborted to be indeterminate to ensure that + * the transaction completion guarantee is never broken. + */ + ereport(WARNING, + (errcode(ERRCODE_ADMIN_SHUTDOWN), + errmsg("terminating connection because fast shutdown is requested"), + errdetail("This connection requested synchronous replication at commit" + " yet confirmation of replication has not been received." + " The transaction has committed locally and might be committed" + " on recently disconnected standby servers also."))); + + /* + * We DO NOT want to run proc_exit() callbacks -- we're here because + * we are shutting down and don't want any code to stall or + * prevent that. + */ + on_exit_reset(); + + /* + * Note we do exit(0) not exit(>0). This is to avoid forcing + * postmaster into a system reset cycle. + */ + exit(0); + } else if (RecoveryConflictPending && RecoveryConflictRetryable) { pgstat_report_recovery_conflict(RecoveryConflictReason); *** a/src/include/miscadmin.h --- b/src/include/miscadmin.h *************** *** 78,83 **** extern PGDLLIMPORT volatile uint32 CritSectionCount; --- 78,86 ---- /* in tcop/postgres.c */ extern void ProcessInterrupts(void); + /* in replication/syncrep.c */ + extern bool WaitingForSyncRep; + #ifndef WIN32 #define CHECK_FOR_INTERRUPTS() \