diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index 1495bb4..cedf5ee 100644
*** a/src/backend/access/transam/xact.c
--- b/src/backend/access/transam/xact.c
*************** static void CallSubXactCallbacks(SubXact
*** 274,280 ****
  static void CleanupTransaction(void);
  static void CheckTransactionChain(bool isTopLevel, bool throwError,
  					  const char *stmtType);
! static void CommitTransaction(void);
  static TransactionId RecordTransactionAbort(bool isSubXact);
  static void StartTransaction(void);
  
--- 274,280 ----
  static void CleanupTransaction(void);
  static void CheckTransactionChain(bool isTopLevel, bool throwError,
  					  const char *stmtType);
! static void CommitTransaction(bool keep_holdoff);
  static TransactionId RecordTransactionAbort(bool isSubXact);
  static void StartTransaction(void);
  
*************** StartTransaction(void)
*** 1762,1771 ****
  /*
   *	CommitTransaction
   *
   * NB: if you change this routine, better look at PrepareTransaction too!
   */
  static void
! CommitTransaction(void)
  {
  	TransactionState s = CurrentTransactionState;
  	TransactionId latestXid;
--- 1762,1775 ----
  /*
   *	CommitTransaction
   *
+  * If keep_holdoff is true, we return with interrupts still held off;
+  * this is appropriate if caller has something to do that should be
+  * considered part of post-commit cleanup.
+  *
   * NB: if you change this routine, better look at PrepareTransaction too!
   */
  static void
! CommitTransaction(bool keep_holdoff)
  {
  	TransactionState s = CurrentTransactionState;
  	TransactionId latestXid;
*************** CommitTransaction(void)
*** 1837,1843 ****
  	 */
  	PreCommit_Notify();
  
! 	/* Prevent cancel/die interrupt while cleaning up */
  	HOLD_INTERRUPTS();
  
  	/* Commit updates to the relation map --- do this as late as possible */
--- 1841,1851 ----
  	 */
  	PreCommit_Notify();
  
! 	/*
! 	 * Prevent cancel/die interrupt while cleaning up.  If caller passes
! 	 * keep_holdoff = true, interrupts will remain held till caller resumes
! 	 * them.
! 	 */
  	HOLD_INTERRUPTS();
  
  	/* Commit updates to the relation map --- do this as late as possible */
*************** CommitTransaction(void)
*** 1958,1974 ****
  	 */
  	s->state = TRANS_DEFAULT;
  
! 	RESUME_INTERRUPTS();
  }
  
  
  /*
   *	PrepareTransaction
   *
   * NB: if you change this routine, better look at CommitTransaction too!
   */
  static void
! PrepareTransaction(void)
  {
  	TransactionState s = CurrentTransactionState;
  	TransactionId xid = GetCurrentTransactionId();
--- 1966,1987 ----
  	 */
  	s->state = TRANS_DEFAULT;
  
! 	if (!keep_holdoff)
! 		RESUME_INTERRUPTS();
  }
  
  
  /*
   *	PrepareTransaction
   *
+  * If keep_holdoff is true, we return with interrupts still held off;
+  * this is appropriate if caller has something to do that should be
+  * considered part of post-commit cleanup.
+  *
   * NB: if you change this routine, better look at CommitTransaction too!
   */
  static void
! PrepareTransaction(bool keep_holdoff)
  {
  	TransactionState s = CurrentTransactionState;
  	TransactionId xid = GetCurrentTransactionId();
*************** PrepareTransaction(void)
*** 2067,2073 ****
  				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
  		errmsg("cannot PREPARE a transaction that has exported snapshots")));
  
! 	/* Prevent cancel/die interrupt while cleaning up */
  	HOLD_INTERRUPTS();
  
  	/*
--- 2080,2090 ----
  				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
  		errmsg("cannot PREPARE a transaction that has exported snapshots")));
  
! 	/*
! 	 * Prevent cancel/die interrupt while cleaning up.  If caller passes
! 	 * keep_holdoff = true, interrupts will remain held till caller resumes
! 	 * them.
! 	 */
  	HOLD_INTERRUPTS();
  
  	/*
*************** PrepareTransaction(void)
*** 2225,2231 ****
  	 */
  	s->state = TRANS_DEFAULT;
  
! 	RESUME_INTERRUPTS();
  }
  
  
--- 2242,2249 ----
  	 */
  	s->state = TRANS_DEFAULT;
  
! 	if (!keep_holdoff)
! 		RESUME_INTERRUPTS();
  }
  
  
*************** StartTransactionCommand(void)
*** 2492,2500 ****
  
  /*
   *	CommitTransactionCommand
   */
  void
! CommitTransactionCommand(void)
  {
  	TransactionState s = CurrentTransactionState;
  
--- 2510,2524 ----
  
  /*
   *	CommitTransactionCommand
+  *
+  * If keep_holdoff is true, and we perform a transaction commit or prepare,
+  * we return with interrupts still held off; this is appropriate if caller has
+  * something to do that should be considered part of post-commit cleanup.
+  * Note that callers passing "true" must be prepared for either the case that
+  * interrupts are held or that they're not.
   */
  void
! CommitTransactionCommand(bool keep_holdoff)
  {
  	TransactionState s = CurrentTransactionState;
  
*************** CommitTransactionCommand(void)
*** 2515,2521 ****
  			 * transaction commit, and return to the idle state.
  			 */
  		case TBLOCK_STARTED:
! 			CommitTransaction();
  			s->blockState = TBLOCK_DEFAULT;
  			break;
  
--- 2539,2545 ----
  			 * transaction commit, and return to the idle state.
  			 */
  		case TBLOCK_STARTED:
! 			CommitTransaction(keep_holdoff);
  			s->blockState = TBLOCK_DEFAULT;
  			break;
  
*************** CommitTransactionCommand(void)
*** 2544,2550 ****
  			 * idle state.
  			 */
  		case TBLOCK_END:
! 			CommitTransaction();
  			s->blockState = TBLOCK_DEFAULT;
  			break;
  
--- 2568,2574 ----
  			 * idle state.
  			 */
  		case TBLOCK_END:
! 			CommitTransaction(keep_holdoff);
  			s->blockState = TBLOCK_DEFAULT;
  			break;
  
*************** CommitTransactionCommand(void)
*** 2583,2589 ****
  			 * return to the idle state.
  			 */
  		case TBLOCK_PREPARE:
! 			PrepareTransaction();
  			s->blockState = TBLOCK_DEFAULT;
  			break;
  
--- 2607,2613 ----
  			 * return to the idle state.
  			 */
  		case TBLOCK_PREPARE:
! 			PrepareTransaction(keep_holdoff);
  			s->blockState = TBLOCK_DEFAULT;
  			break;
  
*************** CommitTransactionCommand(void)
*** 2634,2646 ****
  			if (s->blockState == TBLOCK_END)
  			{
  				Assert(s->parent == NULL);
! 				CommitTransaction();
  				s->blockState = TBLOCK_DEFAULT;
  			}
  			else if (s->blockState == TBLOCK_PREPARE)
  			{
  				Assert(s->parent == NULL);
! 				PrepareTransaction();
  				s->blockState = TBLOCK_DEFAULT;
  			}
  			else
--- 2658,2670 ----
  			if (s->blockState == TBLOCK_END)
  			{
  				Assert(s->parent == NULL);
! 				CommitTransaction(keep_holdoff);
  				s->blockState = TBLOCK_DEFAULT;
  			}
  			else if (s->blockState == TBLOCK_PREPARE)
  			{
  				Assert(s->parent == NULL);
! 				PrepareTransaction(keep_holdoff);
  				s->blockState = TBLOCK_DEFAULT;
  			}
  			else
*************** CommitTransactionCommand(void)
*** 2655,2661 ****
  			 */
  		case TBLOCK_SUBABORT_END:
  			CleanupSubTransaction();
! 			CommitTransactionCommand();
  			break;
  
  			/*
--- 2679,2685 ----
  			 */
  		case TBLOCK_SUBABORT_END:
  			CleanupSubTransaction();
! 			CommitTransactionCommand(keep_holdoff);
  			break;
  
  			/*
*************** CommitTransactionCommand(void)
*** 2664,2670 ****
  		case TBLOCK_SUBABORT_PENDING:
  			AbortSubTransaction();
  			CleanupSubTransaction();
! 			CommitTransactionCommand();
  			break;
  
  			/*
--- 2688,2694 ----
  		case TBLOCK_SUBABORT_PENDING:
  			AbortSubTransaction();
  			CleanupSubTransaction();
! 			CommitTransactionCommand(keep_holdoff);
  			break;
  
  			/*
*************** BeginInternalSubTransaction(char *name)
*** 3779,3785 ****
  			break;
  	}
  
! 	CommitTransactionCommand();
  	StartTransactionCommand();
  }
  
--- 3803,3809 ----
  			break;
  	}
  
! 	CommitTransactionCommand(false);
  	StartTransactionCommand();
  }
  
diff --git a/src/backend/bootstrap/bootparse.y b/src/backend/bootstrap/bootparse.y
index 6e563b6..cb14f08 100644
*** a/src/backend/bootstrap/bootparse.y
--- b/src/backend/bootstrap/bootparse.y
*************** do_start(void)
*** 77,83 ****
  static void
  do_end(void)
  {
! 	CommitTransactionCommand();
  	elog(DEBUG4, "commit transaction");
  	CHECK_FOR_INTERRUPTS();		/* allow SIGINT to kill bootstrap run */
  	if (isatty(0))
--- 77,83 ----
  static void
  do_end(void)
  {
! 	CommitTransactionCommand(false);
  	elog(DEBUG4, "commit transaction");
  	CHECK_FOR_INTERRUPTS();		/* allow SIGINT to kill bootstrap run */
  	if (isatty(0))
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index f85ed93..0bef8ad 100644
*** a/src/backend/catalog/index.c
--- b/src/backend/catalog/index.c
*************** index_drop(Oid indexId, bool concurrent)
*** 1453,1459 ****
  		LockRelationIdForSession(&indexrelid, ShareUpdateExclusiveLock);
  
  		PopActiveSnapshot();
! 		CommitTransactionCommand();
  		StartTransactionCommand();
  
  		/*
--- 1453,1459 ----
  		LockRelationIdForSession(&indexrelid, ShareUpdateExclusiveLock);
  
  		PopActiveSnapshot();
! 		CommitTransactionCommand(false);
  		StartTransactionCommand();
  
  		/*
*************** index_drop(Oid indexId, bool concurrent)
*** 1507,1513 ****
  		 * Again, commit the transaction to make the pg_index update visible
  		 * to other sessions.
  		 */
! 		CommitTransactionCommand();
  		StartTransactionCommand();
  
  		/*
--- 1507,1513 ----
  		 * Again, commit the transaction to make the pg_index update visible
  		 * to other sessions.
  		 */
! 		CommitTransactionCommand(false);
  		StartTransactionCommand();
  
  		/*
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index 1af977c..460c1fd 100644
*** a/src/backend/catalog/namespace.c
--- b/src/backend/catalog/namespace.c
*************** RemoveTempRelationsCallback(int code, Da
*** 3855,3861 ****
  
  		RemoveTempRelations(myTempNamespace);
  
! 		CommitTransactionCommand();
  	}
  }
  
--- 3855,3861 ----
  
  		RemoveTempRelations(myTempNamespace);
  
! 		CommitTransactionCommand(false);
  	}
  }
  
diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c
index 2826b7e..1bee7a6 100644
*** a/src/backend/commands/async.c
--- b/src/backend/commands/async.c
*************** ProcessCompletedNotifies(void)
*** 1104,1110 ****
  		asyncQueueAdvanceTail();
  	}
  
! 	CommitTransactionCommand();
  
  	MemoryContextSwitchTo(caller_context);
  
--- 1104,1110 ----
  		asyncQueueAdvanceTail();
  	}
  
! 	CommitTransactionCommand(false);
  
  	MemoryContextSwitchTo(caller_context);
  
*************** ProcessIncomingNotify(void)
*** 1988,1994 ****
  
  	asyncQueueReadAllNotifications();
  
! 	CommitTransactionCommand();
  
  	/*
  	 * Must flush the notify messages to ensure frontend gets them promptly.
--- 1988,1994 ----
  
  	asyncQueueReadAllNotifications();
  
! 	CommitTransactionCommand(false);
  
  	/*
  	 * Must flush the notify messages to ensure frontend gets them promptly.
diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c
index 3febdd5..1c5d476 100644
*** a/src/backend/commands/cluster.c
--- b/src/backend/commands/cluster.c
*************** cluster(ClusterStmt *stmt, bool isTopLev
*** 214,220 ****
  
  		/* Commit to get out of starting transaction */
  		PopActiveSnapshot();
! 		CommitTransactionCommand();
  
  		/* Ok, now that we've got them all, cluster them one by one */
  		foreach(rv, rvs)
--- 214,220 ----
  
  		/* Commit to get out of starting transaction */
  		PopActiveSnapshot();
! 		CommitTransactionCommand(false);
  
  		/* Ok, now that we've got them all, cluster them one by one */
  		foreach(rv, rvs)
*************** cluster(ClusterStmt *stmt, bool isTopLev
*** 228,234 ****
  			/* Do the job. */
  			cluster_rel(rvtc->tableOid, rvtc->indexOid, true, stmt->verbose);
  			PopActiveSnapshot();
! 			CommitTransactionCommand();
  		}
  
  		/* Start a new transaction for the cleanup work. */
--- 228,234 ----
  			/* Do the job. */
  			cluster_rel(rvtc->tableOid, rvtc->indexOid, true, stmt->verbose);
  			PopActiveSnapshot();
! 			CommitTransactionCommand(false);
  		}
  
  		/* Start a new transaction for the cleanup work. */
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index a699ce3..8f7a51f 100644
*** a/src/backend/commands/dbcommands.c
--- b/src/backend/commands/dbcommands.c
*************** movedb(const char *dbname, const char *t
*** 1312,1318 ****
  	 * really commits.
  	 */
  	PopActiveSnapshot();
! 	CommitTransactionCommand();
  
  	/* Start new transaction for the remaining work; don't need a snapshot */
  	StartTransactionCommand();
--- 1312,1318 ----
  	 * really commits.
  	 */
  	PopActiveSnapshot();
! 	CommitTransactionCommand(false);
  
  	/* Start new transaction for the remaining work; don't need a snapshot */
  	StartTransactionCommand();
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 1c1d0da..b76738c 100644
*** a/src/backend/commands/indexcmds.c
--- b/src/backend/commands/indexcmds.c
*************** DefineIndex(Oid relationId,
*** 663,669 ****
  	LockRelationIdForSession(&heaprelid, ShareUpdateExclusiveLock);
  
  	PopActiveSnapshot();
! 	CommitTransactionCommand();
  	StartTransactionCommand();
  
  	/*
--- 663,669 ----
  	LockRelationIdForSession(&heaprelid, ShareUpdateExclusiveLock);
  
  	PopActiveSnapshot();
! 	CommitTransactionCommand(false);
  	StartTransactionCommand();
  
  	/*
*************** DefineIndex(Oid relationId,
*** 737,743 ****
  	/*
  	 * Commit this transaction to make the indisready update visible.
  	 */
! 	CommitTransactionCommand();
  	StartTransactionCommand();
  
  	/*
--- 737,743 ----
  	/*
  	 * Commit this transaction to make the indisready update visible.
  	 */
! 	CommitTransactionCommand(false);
  	StartTransactionCommand();
  
  	/*
*************** ReindexMultipleTables(const char *object
*** 1914,1920 ****
  
  	/* Now reindex each rel in a separate transaction */
  	PopActiveSnapshot();
! 	CommitTransactionCommand();
  	foreach(l, relids)
  	{
  		Oid			relid = lfirst_oid(l);
--- 1914,1920 ----
  
  	/* Now reindex each rel in a separate transaction */
  	PopActiveSnapshot();
! 	CommitTransactionCommand(false);
  	foreach(l, relids)
  	{
  		Oid			relid = lfirst_oid(l);
*************** ReindexMultipleTables(const char *object
*** 1930,1936 ****
  							get_namespace_name(get_rel_namespace(relid)),
  							get_rel_name(relid))));
  		PopActiveSnapshot();
! 		CommitTransactionCommand();
  	}
  	StartTransactionCommand();
  
--- 1930,1936 ----
  							get_namespace_name(get_rel_namespace(relid)),
  							get_rel_name(relid))));
  		PopActiveSnapshot();
! 		CommitTransactionCommand(false);
  	}
  	StartTransactionCommand();
  
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index bd57b68..c69610d 100644
*** a/src/backend/commands/vacuum.c
--- b/src/backend/commands/vacuum.c
*************** vacuum(int options, RangeVar *relation, 
*** 263,269 ****
  			PopActiveSnapshot();
  
  		/* matches the StartTransaction in PostgresMain() */
! 		CommitTransactionCommand();
  	}
  
  	/* Turn vacuum cost accounting on or off */
--- 263,269 ----
  			PopActiveSnapshot();
  
  		/* matches the StartTransaction in PostgresMain() */
! 		CommitTransactionCommand(false);
  	}
  
  	/* Turn vacuum cost accounting on or off */
*************** vacuum(int options, RangeVar *relation, 
*** 310,316 ****
  				if (use_own_xacts)
  				{
  					PopActiveSnapshot();
! 					CommitTransactionCommand();
  				}
  			}
  		}
--- 310,316 ----
  				if (use_own_xacts)
  				{
  					PopActiveSnapshot();
! 					CommitTransactionCommand(false);
  				}
  			}
  		}
*************** vacuum_rel(Oid relid, RangeVar *relation
*** 1243,1249 ****
  	if (!onerel)
  	{
  		PopActiveSnapshot();
! 		CommitTransactionCommand();
  		return false;
  	}
  
--- 1243,1249 ----
  	if (!onerel)
  	{
  		PopActiveSnapshot();
! 		CommitTransactionCommand(false);
  		return false;
  	}
  
*************** vacuum_rel(Oid relid, RangeVar *relation
*** 1274,1280 ****
  							RelationGetRelationName(onerel))));
  		relation_close(onerel, lmode);
  		PopActiveSnapshot();
! 		CommitTransactionCommand();
  		return false;
  	}
  
--- 1274,1280 ----
  							RelationGetRelationName(onerel))));
  		relation_close(onerel, lmode);
  		PopActiveSnapshot();
! 		CommitTransactionCommand(false);
  		return false;
  	}
  
*************** vacuum_rel(Oid relid, RangeVar *relation
*** 1292,1298 ****
  						RelationGetRelationName(onerel))));
  		relation_close(onerel, lmode);
  		PopActiveSnapshot();
! 		CommitTransactionCommand();
  		return false;
  	}
  
--- 1292,1298 ----
  						RelationGetRelationName(onerel))));
  		relation_close(onerel, lmode);
  		PopActiveSnapshot();
! 		CommitTransactionCommand(false);
  		return false;
  	}
  
*************** vacuum_rel(Oid relid, RangeVar *relation
*** 1307,1313 ****
  	{
  		relation_close(onerel, lmode);
  		PopActiveSnapshot();
! 		CommitTransactionCommand();
  		return false;
  	}
  
--- 1307,1313 ----
  	{
  		relation_close(onerel, lmode);
  		PopActiveSnapshot();
! 		CommitTransactionCommand(false);
  		return false;
  	}
  
*************** vacuum_rel(Oid relid, RangeVar *relation
*** 1375,1381 ****
  	 * Complete the transaction and free all temporary memory used.
  	 */
  	PopActiveSnapshot();
! 	CommitTransactionCommand();
  
  	/*
  	 * If the relation has a secondary toast rel, vacuum that too while we
--- 1375,1381 ----
  	 * Complete the transaction and free all temporary memory used.
  	 */
  	PopActiveSnapshot();
! 	CommitTransactionCommand(false);
  
  	/*
  	 * If the relation has a secondary toast rel, vacuum that too while we
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index 5ccae24..b593437 100644
*** a/src/backend/postmaster/autovacuum.c
--- b/src/backend/postmaster/autovacuum.c
*************** get_database_list(void)
*** 1847,1853 ****
  	heap_endscan(scan);
  	heap_close(rel, AccessShareLock);
  
! 	CommitTransactionCommand();
  
  	return dblist;
  }
--- 1847,1853 ----
  	heap_endscan(scan);
  	heap_close(rel, AccessShareLock);
  
! 	CommitTransactionCommand(false);
  
  	return dblist;
  }
*************** deleted:
*** 2355,2361 ****
  	vac_update_datfrozenxid();
  
  	/* Finally close out the last transaction. */
! 	CommitTransactionCommand();
  }
  
  /*
--- 2355,2361 ----
  	vac_update_datfrozenxid();
  
  	/* Finally close out the last transaction. */
! 	CommitTransactionCommand(false);
  }
  
  /*
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index 2956119..833fd69 100644
*** a/src/backend/replication/walsender.c
--- b/src/backend/replication/walsender.c
*************** IdentifySystem(void)
*** 331,337 ****
  		/* make dbname live outside TX context */
  		MemoryContextSwitchTo(cur);
  		dbname = get_database_name(MyDatabaseId);
! 		CommitTransactionCommand();
  		/* CommitTransactionCommand switches to TopMemoryContext */
  		MemoryContextSwitchTo(cur);
  	}
--- 331,337 ----
  		/* make dbname live outside TX context */
  		MemoryContextSwitchTo(cur);
  		dbname = get_database_name(MyDatabaseId);
! 		CommitTransactionCommand(false);
  		/* CommitTransactionCommand switches to TopMemoryContext */
  		MemoryContextSwitchTo(cur);
  	}
diff --git a/src/backend/storage/ipc/sinval.c b/src/backend/storage/ipc/sinval.c
index 67ec515..ed3961e 100644
*** a/src/backend/storage/ipc/sinval.c
--- b/src/backend/storage/ipc/sinval.c
*************** ProcessCatchupInterrupt(void)
*** 200,206 ****
  		{
  			elog(DEBUG4, "ProcessCatchupEvent outside transaction");
  			StartTransactionCommand();
! 			CommitTransactionCommand();
  		}
  	}
  }
--- 200,206 ----
  		{
  			elog(DEBUG4, "ProcessCatchupEvent outside transaction");
  			StartTransactionCommand();
! 			CommitTransactionCommand(false);
  		}
  	}
  }
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 33720e8..ab361cd 100644
*** a/src/backend/tcop/postgres.c
--- b/src/backend/tcop/postgres.c
*************** static int	errdetail_params(ParamListInf
*** 190,196 ****
  static int	errdetail_abort(void);
  static int	errdetail_recovery_conflict(void);
  static void start_xact_command(void);
! static void finish_xact_command(void);
  static bool IsTransactionExitStmt(Node *parsetree);
  static bool IsTransactionExitStmtList(List *parseTrees);
  static bool IsTransactionStmtList(List *parseTrees);
--- 190,196 ----
  static int	errdetail_abort(void);
  static int	errdetail_recovery_conflict(void);
  static void start_xact_command(void);
! static void finish_xact_command(bool keep_holdoff);
  static bool IsTransactionExitStmt(Node *parsetree);
  static bool IsTransactionExitStmtList(List *parseTrees);
  static bool IsTransactionStmtList(List *parseTrees);
*************** exec_simple_query(const char *query_stri
*** 1111,1125 ****
  
  		PortalDrop(portal, false);
  
! 		if (IsA(parsetree, TransactionStmt))
! 		{
! 			/*
! 			 * If this was a transaction control statement, commit it. We will
! 			 * start a new xact command for the next command (if any).
! 			 */
! 			finish_xact_command();
! 		}
! 		else if (lnext(parsetree_item) == NULL)
  		{
  			/*
  			 * If this is the last parsetree of the query string, close down
--- 1111,1117 ----
  
  		PortalDrop(portal, false);
  
! 		if (lnext(parsetree_item) == NULL)
  		{
  			/*
  			 * If this is the last parsetree of the query string, close down
*************** exec_simple_query(const char *query_stri
*** 1131,1137 ****
  			 * historical Postgres behavior, we do not force a transaction
  			 * boundary between queries appearing in a single query string.
  			 */
! 			finish_xact_command();
  		}
  		else
  		{
--- 1123,1138 ----
  			 * historical Postgres behavior, we do not force a transaction
  			 * boundary between queries appearing in a single query string.
  			 */
! 			finish_xact_command(true);
! 		}
! 		else if (IsA(parsetree, TransactionStmt))
! 		{
! 			/*
! 			 * If this was a transaction control statement, commit it. We will
! 			 * start a new xact command for the next command.  We know there
! 			 * is another one, so don't hold off interrupts.
! 			 */
! 			finish_xact_command(false);
  		}
  		else
  		{
*************** exec_simple_query(const char *query_stri
*** 1154,1160 ****
  	/*
  	 * Close down transaction statement, if one is open.
  	 */
! 	finish_xact_command();
  
  	/*
  	 * If there were no parsetrees, return EmptyQueryResponse message.
--- 1155,1161 ----
  	/*
  	 * Close down transaction statement, if one is open.
  	 */
! 	finish_xact_command(true);
  
  	/*
  	 * If there were no parsetrees, return EmptyQueryResponse message.
*************** exec_execute_message(const char *portal_
*** 2001,2007 ****
  			 * If this was a transaction control statement, commit it.  We
  			 * will start a new xact command for the next command (if any).
  			 */
! 			finish_xact_command();
  		}
  		else
  		{
--- 2002,2008 ----
  			 * If this was a transaction control statement, commit it.  We
  			 * will start a new xact command for the next command (if any).
  			 */
! 			finish_xact_command(true);
  		}
  		else
  		{
*************** start_xact_command(void)
*** 2453,2459 ****
  }
  
  static void
! finish_xact_command(void)
  {
  	if (xact_started)
  	{
--- 2454,2460 ----
  }
  
  static void
! finish_xact_command(bool keep_holdoff)
  {
  	if (xact_started)
  	{
*************** finish_xact_command(void)
*** 2464,2470 ****
  		ereport(DEBUG3,
  				(errmsg_internal("CommitTransactionCommand")));
  
! 		CommitTransactionCommand();
  
  #ifdef MEMORY_CONTEXT_CHECKING
  		/* Check all memory contexts that weren't freed during commit */
--- 2465,2471 ----
  		ereport(DEBUG3,
  				(errmsg_internal("CommitTransactionCommand")));
  
! 		CommitTransactionCommand(keep_holdoff);
  
  #ifdef MEMORY_CONTEXT_CHECKING
  		/* Check all memory contexts that weren't freed during commit */
*************** PostgresMain(int argc, char *argv[],
*** 3964,3969 ****
--- 3965,3976 ----
  		}
  
  		/*
+ 		 * Resume interrupts, in case they were held off thanks to a COMMIT.
+ 		 */
+ 		InterruptHoldoffCount = 0;
+ 		CHECK_FOR_INTERRUPTS();
+ 
+ 		/*
  		 * (2) Allow asynchronous signals to be executed immediately if they
  		 * come in while we are waiting for client input. (This must be
  		 * conditional since we don't want, say, reads on behalf of COPY FROM
*************** PostgresMain(int argc, char *argv[],
*** 4127,4133 ****
  				}
  
  				/* commit the function-invocation transaction */
! 				finish_xact_command();
  
  				send_ready_for_query = true;
  				break;
--- 4134,4140 ----
  				}
  
  				/* commit the function-invocation transaction */
! 				finish_xact_command(true);
  
  				send_ready_for_query = true;
  				break;
*************** PostgresMain(int argc, char *argv[],
*** 4216,4222 ****
  
  			case 'S':			/* sync */
  				pq_getmsgend(&input_message);
! 				finish_xact_command();
  				send_ready_for_query = true;
  				break;
  
--- 4223,4229 ----
  
  			case 'S':			/* sync */
  				pq_getmsgend(&input_message);
! 				finish_xact_command(true);
  				send_ready_for_query = true;
  				break;
  
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index 1e646a1..59eb697 100644
*** a/src/backend/utils/init/postinit.c
--- b/src/backend/utils/init/postinit.c
*************** InitPostgres(const char *in_dbname, Oid 
*** 794,800 ****
  		pgstat_bestart();
  
  		/* close the transaction we started above */
! 		CommitTransactionCommand();
  
  		return;
  	}
--- 794,800 ----
  		pgstat_bestart();
  
  		/* close the transaction we started above */
! 		CommitTransactionCommand(false);
  
  		return;
  	}
*************** InitPostgres(const char *in_dbname, Oid 
*** 973,979 ****
  
  	/* close the transaction we started above */
  	if (!bootstrap)
! 		CommitTransactionCommand();
  }
  
  /*
--- 973,979 ----
  
  	/* close the transaction we started above */
  	if (!bootstrap)
! 		CommitTransactionCommand(false);
  }
  
  /*
diff --git a/src/include/access/xact.h b/src/include/access/xact.h
index fdf3ea3..59e5df0 100644
*** a/src/include/access/xact.h
--- b/src/include/access/xact.h
*************** extern bool TransactionIdIsCurrentTransa
*** 308,314 ****
  extern void CommandCounterIncrement(void);
  extern void ForceSyncCommit(void);
  extern void StartTransactionCommand(void);
! extern void CommitTransactionCommand(void);
  extern void AbortCurrentTransaction(void);
  extern void BeginTransactionBlock(void);
  extern bool EndTransactionBlock(void);
--- 308,314 ----
  extern void CommandCounterIncrement(void);
  extern void ForceSyncCommit(void);
  extern void StartTransactionCommand(void);
! extern void CommitTransactionCommand(bool keep_holdoff);
  extern void AbortCurrentTransaction(void);
  extern void BeginTransactionBlock(void);
  extern bool EndTransactionBlock(void);
diff --git a/src/test/modules/worker_spi/worker_spi.c b/src/test/modules/worker_spi/worker_spi.c
index 4149c94..c8882ff 100644
*** a/src/test/modules/worker_spi/worker_spi.c
--- b/src/test/modules/worker_spi/worker_spi.c
*************** initialize_worker_spi(worktable *table)
*** 154,160 ****
  
  	SPI_finish();
  	PopActiveSnapshot();
! 	CommitTransactionCommand();
  	pgstat_report_activity(STATE_IDLE, NULL);
  }
  
--- 154,160 ----
  
  	SPI_finish();
  	PopActiveSnapshot();
! 	CommitTransactionCommand(false);
  	pgstat_report_activity(STATE_IDLE, NULL);
  }
  
*************** worker_spi_main(Datum main_arg)
*** 291,297 ****
  		 */
  		SPI_finish();
  		PopActiveSnapshot();
! 		CommitTransactionCommand();
  		pgstat_report_activity(STATE_IDLE, NULL);
  	}
  
--- 291,297 ----
  		 */
  		SPI_finish();
  		PopActiveSnapshot();
! 		CommitTransactionCommand(false);
  		pgstat_report_activity(STATE_IDLE, NULL);
  	}
  
