From 3f0fa93cfc2442cb4952fa824525b4d7b4346db7 Mon Sep 17 00:00:00 2001
From: Bruce Momjian <bruce@momjian.us>
Date: Tue, 17 Aug 2004 16:54:47 +0000
Subject: [PATCH] Chain on to SIGPIPE handler rather than just do action on
 default.

Always create thread-specific variable.
---
 doc/src/sgml/libpq.sgml          |  5 ++---
 src/interfaces/libpq/fe-secure.c | 38 ++++++++++++++------------------
 2 files changed, 19 insertions(+), 24 deletions(-)

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index af9a35a620d..06c93306432 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.159 2004/08/16 02:12:29 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.160 2004/08/17 16:54:46 momjian Exp $
 -->
 
  <chapter id="libpq">
@@ -3738,8 +3738,7 @@ When <productname>PostgreSQL</> is configured without
 <function>send()</> call and restores the original signal handler after
 completion. When <literal>--enable-thread-safety</> is used,
 <application>libpq</> installs its own <literal>SIGPIPE</> handler
-before the first database connection if no custom <literal>SIGPIPE</>
-handler has been installed previously. This handler uses thread-local
+before the first database connection.  This handler uses thread-local
 storage to determine if a <literal>SIGPIPE</> signal has been generated
 by a libpq <function>send()</>. If an application wants to install
 its own <literal>SIGPIPE</> signal handler, it should call
diff --git a/src/interfaces/libpq/fe-secure.c b/src/interfaces/libpq/fe-secure.c
index dac639c8e48..6313dc146f0 100644
--- a/src/interfaces/libpq/fe-secure.c
+++ b/src/interfaces/libpq/fe-secure.c
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.46 2004/08/17 04:24:23 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.47 2004/08/17 16:54:47 momjian Exp $
  *
  * NOTES
  *	  The client *requires* a valid server certificate.  Since
@@ -152,7 +152,8 @@ static SSL_CTX *SSL_context = NULL;
 
 #ifdef ENABLE_THREAD_SAFETY
 static void sigpipe_handler_ignore_send(int signo);
-pthread_key_t pq_thread_in_send = 0;
+pthread_key_t pq_thread_in_send = 0;	/* initializer needed on Darwin */
+static pqsigfunc pq_pipe_handler;
 #endif
 
 /* ------------------------------------------------------------ */
@@ -1190,23 +1191,12 @@ PQgetssl(PGconn *conn)
 void
 pq_check_sigpipe_handler(void)
 {
-	pqsigfunc pipehandler;
-
+	pthread_key_create(&pq_thread_in_send, NULL);
 	/*
-	 *	If the app hasn't set a SIGPIPE handler, define our own
-	 *	that ignores SIGPIPE on libpq send() and does SIG_DFL
-	 *	for other SIGPIPE cases.
+	 *	Find current pipe handler and chain on to it.
 	 */
-	pipehandler = pqsignalinquire(SIGPIPE);
-	if (pipehandler == SIG_DFL)	/* not set by application */
-	{
-		/*
-		 *	Create key first because the signal handler might be called
-		 *	right after being installed.
-		 */
-		pthread_key_create(&pq_thread_in_send, NULL);	
-		pqsignal(SIGPIPE, sigpipe_handler_ignore_send);
-	}
+	pq_pipe_handler = pqsignalinquire(SIGPIPE);
+	pqsignal(SIGPIPE, sigpipe_handler_ignore_send);
 }
 
 /*
@@ -1216,12 +1206,18 @@ void
 sigpipe_handler_ignore_send(int signo)
 {
 	/*
-	 *	If we have gotten a SIGPIPE outside send(), exit.
-	 *	Synchronous signals are delivered to the thread
-	 *	that caused the signal.
+	 *	If we have gotten a SIGPIPE outside send(), chain or
+	 *	exit if we are at the end of the chain.
+	 *	Synchronous signals are delivered to the thread that
+	 *	caused the signal.
 	 */
 	if (!PQinSend())
-		exit(128 + SIGPIPE);	/* typical return value for SIG_DFL */
+	{
+		if (pq_pipe_handler == SIG_DFL)	/* not set by application */
+			exit(128 + SIGPIPE);	/* typical return value for SIG_DFL */
+		else
+			(*pq_pipe_handler)(signo);      /* call original handler */
+	}
 }
 #endif
 #endif
-- 
GitLab