*** a/src/backend/access/transam/xlog.c
--- b/src/backend/access/transam/xlog.c
***************
*** 10628,10640 **** do_pg_start_backup(const char *backupidstr, bool fast, TimeLineID *starttli_p,
  	/*
  	 * Mark that start phase has correctly finished for an exclusive backup.
  	 * Session-level locks are updated as well to reflect that state.
  	 */
  	if (exclusive)
  	{
  		WALInsertLockAcquireExclusive();
  		XLogCtl->Insert.exclusiveBackupState = EXCLUSIVE_BACKUP_IN_PROGRESS;
! 		WALInsertLockRelease();
  		sessionBackupState = SESSION_BACKUP_EXCLUSIVE;
  	}
  	else
  		sessionBackupState = SESSION_BACKUP_NON_EXCLUSIVE;
--- 10628,10647 ----
  	/*
  	 * Mark that start phase has correctly finished for an exclusive backup.
  	 * Session-level locks are updated as well to reflect that state.
+ 	 *
+ 	 * Note that CHECK_FOR_INTERRUPTS() must not occur while updating
+ 	 * backup counters and session-level lock. Otherwise they can be
+ 	 * updated inconsistently, and which might cause do_pg_abort_backup()
+ 	 * to fail.
  	 */
  	if (exclusive)
  	{
  		WALInsertLockAcquireExclusive();
  		XLogCtl->Insert.exclusiveBackupState = EXCLUSIVE_BACKUP_IN_PROGRESS;
! 
! 		/* Set session-level lock */
  		sessionBackupState = SESSION_BACKUP_EXCLUSIVE;
+ 		WALInsertLockRelease();
  	}
  	else
  		sessionBackupState = SESSION_BACKUP_NON_EXCLUSIVE;
***************
*** 10838,10844 **** do_pg_stop_backup(char *labelfile, bool waitforarchive, TimeLineID *stoptli_p)
  	}
  
  	/*
! 	 * OK to update backup counters and forcePageWrites
  	 */
  	WALInsertLockAcquireExclusive();
  	if (exclusive)
--- 10845,10855 ----
  	}
  
  	/*
! 	 * OK to update backup counters, forcePageWrites and session-level lock.
! 	 *
! 	 * Note that CHECK_FOR_INTERRUPTS() must not occur while updating them.
! 	 * Otherwise they can be updated inconsistently, and which might cause
! 	 * do_pg_abort_backup() to fail.
  	 */
  	WALInsertLockAcquireExclusive();
  	if (exclusive)
***************
*** 10862,10872 **** do_pg_stop_backup(char *labelfile, bool waitforarchive, TimeLineID *stoptli_p)
  	{
  		XLogCtl->Insert.forcePageWrites = false;
  	}
- 	WALInsertLockRelease();
  
! 	/* Clean up session-level lock */
  	sessionBackupState = SESSION_BACKUP_NONE;
  
  	/*
  	 * Read and parse the START WAL LOCATION line (this code is pretty crude,
  	 * but we are not expecting any variability in the file format).
--- 10873,10892 ----
  	{
  		XLogCtl->Insert.forcePageWrites = false;
  	}
  
! 	/*
! 	 * Clean up session-level lock.
! 	 *
! 	 * You might think that WALInsertLockRelease() can be called
! 	 * before cleaning up session-level lock because session-level
! 	 * lock doesn't need to be protected with WAL insertion lock.
! 	 * But since CHECK_FOR_INTERRUPTS() can occur in it,
! 	 * session-level lock must be cleaned up before it.
! 	 */
  	sessionBackupState = SESSION_BACKUP_NONE;
  
+ 	WALInsertLockRelease();
+ 
  	/*
  	 * Read and parse the START WAL LOCATION line (this code is pretty crude,
  	 * but we are not expecting any variability in the file format).
***************
*** 11104,11111 **** do_pg_stop_backup(char *labelfile, bool waitforarchive, TimeLineID *stoptli_p)
--- 11124,11139 ----
  void
  do_pg_abort_backup(void)
  {
+ 	/*
+ 	 * Quick exit if session is not keeping around a non-exclusive backup
+ 	 * already started.
+ 	 */
+ 	if (sessionBackupState == SESSION_BACKUP_NONE)
+ 		return;
+ 
  	WALInsertLockAcquireExclusive();
  	Assert(XLogCtl->Insert.nonExclusiveBackups > 0);
+ 	Assert(sessionBackupState == SESSION_BACKUP_NON_EXCLUSIVE);
  	XLogCtl->Insert.nonExclusiveBackups--;
  
  	if (XLogCtl->Insert.exclusiveBackupState == EXCLUSIVE_BACKUP_NONE &&
*** a/src/backend/replication/basebackup.c
--- b/src/backend/replication/basebackup.c
***************
*** 215,221 **** perform_base_backup(basebackup_options *opt)
  	 * Once do_pg_start_backup has been called, ensure that any failure causes
  	 * us to abort the backup so we don't "leak" a backup counter. For this
  	 * reason, *all* functionality between do_pg_start_backup() and
! 	 * do_pg_stop_backup() should be inside the error cleanup block!
  	 */
  
  	PG_ENSURE_ERROR_CLEANUP(base_backup_cleanup, (Datum) 0);
--- 215,221 ----
  	 * Once do_pg_start_backup has been called, ensure that any failure causes
  	 * us to abort the backup so we don't "leak" a backup counter. For this
  	 * reason, *all* functionality between do_pg_start_backup() and
! 	 * the end of do_pg_stop_backup() should be inside the error cleanup block!
  	 */
  
  	PG_ENSURE_ERROR_CLEANUP(base_backup_cleanup, (Datum) 0);
***************
*** 324,333 **** perform_base_backup(basebackup_options *opt)
  			else
  				pq_putemptymessage('c');	/* CopyDone */
  		}
  	}
  	PG_END_ENSURE_ERROR_CLEANUP(base_backup_cleanup, (Datum) 0);
  
- 	endptr = do_pg_stop_backup(labelfile->data, !opt->nowait, &endtli);
  
  	if (opt->includewal)
  	{
--- 324,334 ----
  			else
  				pq_putemptymessage('c');	/* CopyDone */
  		}
+ 
+ 		endptr = do_pg_stop_backup(labelfile->data, !opt->nowait, &endtli);
  	}
  	PG_END_ENSURE_ERROR_CLEANUP(base_backup_cleanup, (Datum) 0);
  
  
  	if (opt->includewal)
  	{
