On Fri, 2011-03-04 at 13:35 +0900, Fujii Masao wrote:
> On Fri, Mar 4, 2011 at 1:27 PM, Fujii Masao <masao.fu...@gmail.com> wrote:
> > On Fri, Mar 4, 2011 at 7:01 AM, Tom Lane <t...@sss.pgh.pa.us> wrote:
> >> Simon Riggs <si...@2ndquadrant.com> writes:
> >>> Anyway, this is code in the interrupt handler and only gets executed
> >>> when we receive SIGTERM for a fast shutdown.
> >>
> >> I trust it's not getting *directly* executed from the interrupt handler,
> >> at least not without ImmediateInterruptOK.
> >
> > Yes, the backend waits for replication while cancel/die interrupt is
> > being blocked, i.e., InterruptHoldoffCount > 0. So SIGTERM doesn't
> > lead the waiting backend to there directly. The backend reaches there
> > after returning the result.
> 
> BTW, this is true in COMMIT and PREPARE cases,

CommitTransaction() calls HOLD_INTERRUPT() and then RESUME_INTERRUPTS(),
which was reasonable before we started waiting for syncrep. The
interrupt does occur *before* we send the message back, but doesn't work
effectively at interrupting the wait in the way you would like.

If we RESUME_INTERRUPTS() prior to waiting and then HOLD again that
would allow all signals not just SIGTERM. We would need to selectively
reject everything except SIGTERM messages.

Ideas?

Alter ProcessInterrupts() to accept an interrupt if ProcDiePending &&
WaitingForSyncRep and InterruptHoldoffCount > 0. That looks a little
scary, but looks like it will work.

>  and false in
> COMMIT PREPARED and ROLLBACK PREPARED cases. In the
> latter cases, HOLD_INTERRUPT() is not called before waiting for
> replication.

-- 
 Simon Riggs           http://www.2ndQuadrant.com/books/
 PostgreSQL Development, 24x7 Support, Training and Services
 
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 3063e0b..5d86deb 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -2843,8 +2843,17 @@ RecoveryConflictInterrupt(ProcSignalReason reason)
 void
 ProcessInterrupts(void)
 {
-	/* OK to accept interrupt now? */
-	if (InterruptHoldoffCount != 0 || CritSectionCount != 0)
+	/* 
+	 * OK to accept interrupt now?
+	 *
+	 * Normally this is very straightforward. We don't accept interrupts
+	 * between HOLD_INTERRUPTS() and RESUME_INTERRUPTS().
+	 *
+	 * For SyncRep, we want to accept SIGTERM signals while other interrupts
+	 * are held, so we have a special case solely when WaitingForSyncRep.
+	 */
+	if ((InterruptHoldoffCount != 0 || CritSectionCount != 0) &&
+		!(WaitingForSyncRep && ProcDiePending))
 		return;
 	InterruptPending = false;
 	if (ProcDiePending)
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to