Here is a set of patches to address this issue.

The first one is a small refactoring of the signal setting portability
business.

The second one fixes the SIGQUIT handler inadvertently unblocking
SIGQUIT within itself.

The third one installs an alarm so that if the ereport() call in
quickdie() doesn't finish after 60 seconds, it skips it and finishes up.
The precise logic of this could be debated, but it more or less appears
to get the job done.
>From d70d637ffe60dd3c73690a2640e84ad6e2cdbb50 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pet...@postgresql.org>
Date: Wed, 16 Dec 2009 14:41:10 +0200
Subject: [PATCH 1/3] If there is no sigdelset(), define it as a macro

Removes some duplicate code that recreated the identical workaround.
---
 src/backend/postmaster/bgwriter.c  |    4 ----
 src/backend/postmaster/walwriter.c |    4 ----
 src/backend/tcop/postgres.c        |    4 ----
 src/include/libpq/pqsignal.h       |    6 ++++--
 4 files changed, 4 insertions(+), 14 deletions(-)

diff --git a/src/backend/postmaster/bgwriter.c b/src/backend/postmaster/bgwriter.c
index a2c32a7..81c0d36 100644
--- a/src/backend/postmaster/bgwriter.c
+++ b/src/backend/postmaster/bgwriter.c
@@ -244,11 +244,7 @@ BackgroundWriterMain(void)
 	pqsignal(SIGWINCH, SIG_DFL);
 
 	/* We allow SIGQUIT (quickdie) at all times */
-#ifdef HAVE_SIGPROCMASK
 	sigdelset(&BlockSig, SIGQUIT);
-#else
-	BlockSig &= ~(sigmask(SIGQUIT));
-#endif
 
 	/*
 	 * Initialize so that first time-driven event happens at the correct time.
diff --git a/src/backend/postmaster/walwriter.c b/src/backend/postmaster/walwriter.c
index 90b8cfe..7d95696 100644
--- a/src/backend/postmaster/walwriter.c
+++ b/src/backend/postmaster/walwriter.c
@@ -126,11 +126,7 @@ WalWriterMain(void)
 	pqsignal(SIGWINCH, SIG_DFL);
 
 	/* We allow SIGQUIT (quickdie) at all times */
-#ifdef HAVE_SIGPROCMASK
 	sigdelset(&BlockSig, SIGQUIT);
-#else
-	BlockSig &= ~(sigmask(SIGQUIT));
-#endif
 
 	/*
 	 * Create a resource owner to keep track of our resources (not clear that
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index c985478..c7906bf 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3292,11 +3292,7 @@ PostgresMain(int argc, char *argv[], const char *username)
 	if (IsUnderPostmaster)
 	{
 		/* We allow SIGQUIT (quickdie) at all times */
-#ifdef HAVE_SIGPROCMASK
 		sigdelset(&BlockSig, SIGQUIT);
-#else
-		BlockSig &= ~(sigmask(SIGQUIT));
-#endif
 	}
 
 	PG_SETMASK(&BlockSig);		/* block everything except SIGQUIT */
diff --git a/src/include/libpq/pqsignal.h b/src/include/libpq/pqsignal.h
index d8e791c..82414d6 100644
--- a/src/include/libpq/pqsignal.h
+++ b/src/include/libpq/pqsignal.h
@@ -26,7 +26,7 @@ extern sigset_t UnBlockSig,
 			StartupBlockSig;
 
 #define PG_SETMASK(mask)	sigprocmask(SIG_SETMASK, mask, NULL)
-#else
+#else /* not HAVE_SIGPROCMASK */
 extern int	UnBlockSig,
 			BlockSig,
 			StartupBlockSig;
@@ -37,7 +37,9 @@ extern int	UnBlockSig,
 #define PG_SETMASK(mask)		pqsigsetmask(*((int*)(mask)))
 int			pqsigsetmask(int mask);
 #endif
-#endif
+
+#define sigdelset(set, signum)	(*(set) &= ~(sigmask(signum)))
+#endif /* not HAVE_SIGPROCMASK */
 
 typedef void (*pqsigfunc) (int);
 
-- 
1.6.5

>From 96a3bc5fe46e226ff179a729baa58efc16c0aaba Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pet...@postgresql.org>
Date: Wed, 16 Dec 2009 16:07:12 +0200
Subject: [PATCH 2/3] Don't unblock SIGQUIT in the SIGQUIT handler

---
 src/backend/tcop/postgres.c  |    1 +
 src/include/libpq/pqsignal.h |    1 +
 2 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index c7906bf..b2fb501 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -2538,6 +2538,7 @@ drop_unnamed_stmt(void)
 void
 quickdie(SIGNAL_ARGS)
 {
+	sigaddset(&BlockSig, SIGQUIT); /* prevent nested calls */
 	PG_SETMASK(&BlockSig);
 
 	/*
diff --git a/src/include/libpq/pqsignal.h b/src/include/libpq/pqsignal.h
index 82414d6..4659ae2 100644
--- a/src/include/libpq/pqsignal.h
+++ b/src/include/libpq/pqsignal.h
@@ -38,6 +38,7 @@ extern int	UnBlockSig,
 int			pqsigsetmask(int mask);
 #endif
 
+#define sigaddset(set, signum)	(*(set) |= (sigmask(signum)))
 #define sigdelset(set, signum)	(*(set) &= ~(sigmask(signum)))
 #endif /* not HAVE_SIGPROCMASK */
 
-- 
1.6.5

>From bebb95abe7a55173cab0558da3373d6a3631465b Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pet...@postgresql.org>
Date: Wed, 16 Dec 2009 17:19:14 +0200
Subject: [PATCH 3/3] Time out the ereport() call in quickdie() after 60 seconds

---
 src/backend/tcop/postgres.c |   25 +++++++++++++++++++++++++
 1 files changed, 25 insertions(+), 0 deletions(-)

diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index b2fb501..ab6805a 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -191,6 +191,7 @@ static bool IsTransactionExitStmtList(List *parseTrees);
 static bool IsTransactionStmtList(List *parseTrees);
 static void drop_unnamed_stmt(void);
 static void SigHupHandler(SIGNAL_ARGS);
+static void quickdie_alarm_handler(SIGNAL_ARGS);
 static void log_disconnections(int code, Datum arg);
 
 
@@ -2539,9 +2540,17 @@ void
 quickdie(SIGNAL_ARGS)
 {
 	sigaddset(&BlockSig, SIGQUIT); /* prevent nested calls */
+	sigdelset(&BlockSig, SIGALRM);
 	PG_SETMASK(&BlockSig);
 
 	/*
+	 * Set up a timeout in case the ereport() call below blocks for a
+	 * long time.
+	 */
+	pqsignal(SIGALRM, quickdie_alarm_handler);
+	alarm(60);
+
+	/*
 	 * If we're aborting out of client auth, don't risk trying to send
 	 * anything to the client; we will likely violate the protocol,
 	 * not to mention that we may have interrupted the guts of OpenSSL
@@ -2586,6 +2595,22 @@ quickdie(SIGNAL_ARGS)
 }
 
 /*
+ * Take over quickdie()'s work if the alarm expired.
+ */
+static void
+quickdie_alarm_handler(SIGNAL_ARGS)
+{
+	/*
+	 * We got here if ereport() was blocking, so don't go there again
+	 * except when really asked for.
+	 */
+	elog(DEBUG5, "quickdie aborted by alarm");
+
+	on_exit_reset();
+	exit(2);
+}
+
+/*
  * Shutdown signal from postmaster: abort transaction and exit
  * at soonest convenient time
  */
-- 
1.6.5

-- 
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