diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index d20d0b601063efb032997ef7aaa3b4e3445e4fbd..41c753a4f8cdb172fb0a17265ab559d098639adb 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.375 2009/06/11 14:49:13 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.376 2009/07/24 17:58:31 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1018,6 +1018,7 @@ PQconnectPoll(PGconn *conn)
 {
 	PGresult   *res;
 	char		sebuf[256];
+	int			optval;
 
 	if (conn == NULL)
 		return PGRES_POLLING_FAILED;
@@ -1153,6 +1154,46 @@ keep_going:						/* We will come back to here until there is
 					}
 #endif   /* F_SETFD */
 
+					/*----------
+					 * We have three methods of blocking SIGPIPE during
+					 * send() calls to this socket:
+					 *
+					 *  - setsockopt(sock, SO_NOSIGPIPE)
+					 *  - send(sock, ..., MSG_NOSIGNAL)
+					 *  - setting the signal mask to SIG_IGN during send()
+					 *
+					 * The third method requires three syscalls per send,
+					 * so we prefer either of the first two, but they are
+					 * less portable.  The state is tracked in the following
+					 * members of PGconn:
+					 *
+					 * conn->sigpipe_so		- we have set up SO_NOSIGPIPE
+					 * conn->sigpipe_flag	- we're specifying MSG_NOSIGNAL
+					 *
+					 * If we can use SO_NOSIGPIPE, then set sigpipe_so here
+					 * and we're done.  Otherwise, set sigpipe_flag so that
+					 * we will try MSG_NOSIGNAL on sends.  If we get an error
+					 * with MSG_NOSIGNAL, we'll clear that flag and revert to
+					 * signal masking.
+					 *----------
+					 */
+					conn->sigpipe_so = false;
+#ifdef MSG_NOSIGNAL
+					conn->sigpipe_flag = true;
+#else
+					conn->sigpipe_flag = false;
+#endif /* MSG_NOSIGNAL */
+
+#ifdef SO_NOSIGPIPE
+					optval = 1;
+					if (setsockopt(conn->sock, SOL_SOCKET, SO_NOSIGPIPE,
+								   (char *) &optval, sizeof(optval)) == 0)
+					{
+						conn->sigpipe_so = true;
+						conn->sigpipe_flag = false;
+					}
+#endif /* SO_NOSIGPIPE */
+
 					/*
 					 * Start/make connection.  This should not block, since we
 					 * are in nonblock mode.  If it does, well, too bad.
@@ -1214,7 +1255,6 @@ keep_going:						/* We will come back to here until there is
 
 		case CONNECTION_STARTED:
 			{
-				int			optval;
 				ACCEPT_TYPE_ARG3 optlen = sizeof(optval);
 
 				/*
diff --git a/src/interfaces/libpq/fe-secure.c b/src/interfaces/libpq/fe-secure.c
index c6e64147872ad45232c46c7d30513845d75d705c..dbd37d50390d7aa6a92591dd2289151442c4b5d0 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.127 2009/06/23 18:13:23 mha Exp $
+ *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.128 2009/07/24 17:58:31 tgl Exp $
  *
  * NOTES
  *
@@ -118,44 +118,76 @@ static long win32_ssl_create_mutex = 0;
 
 /*
  * Macros to handle disabling and then restoring the state of SIGPIPE handling.
- * Note that DISABLE_SIGPIPE() must appear at the start of a block.
+ * On Windows, these are all no-ops since there's no SIGPIPEs.
  */
 
 #ifndef WIN32
+
+#define SIGPIPE_MASKED(conn)	((conn)->sigpipe_so || (conn)->sigpipe_flag)
+
 #ifdef ENABLE_THREAD_SAFETY
 
-#define DISABLE_SIGPIPE(failaction) \
-	sigset_t	osigmask; \
-	bool		sigpipe_pending; \
-	bool		got_epipe = false; \
-\
-	if (pq_block_sigpipe(&osigmask, &sigpipe_pending) < 0) \
-		failaction
+struct sigpipe_info
+{
+	sigset_t	oldsigmask;
+	bool		sigpipe_pending;
+	bool		got_epipe;
+};
 
-#define REMEMBER_EPIPE(cond) \
+#define DECLARE_SIGPIPE_INFO(spinfo) struct sigpipe_info spinfo
+
+#define DISABLE_SIGPIPE(conn, spinfo, failaction) \
+	do { \
+		(spinfo).got_epipe = false; \
+		if (!SIGPIPE_MASKED(conn)) \
+		{ \
+			if (pq_block_sigpipe(&(spinfo).oldsigmask, \
+								 &(spinfo).sigpipe_pending) < 0) \
+				failaction; \
+		} \
+	} while (0)
+
+#define REMEMBER_EPIPE(spinfo, cond) \
 	do { \
 		if (cond) \
-			got_epipe = true; \
+			(spinfo).got_epipe = true; \
 	} while (0)
 
-#define RESTORE_SIGPIPE() \
-	pq_reset_sigpipe(&osigmask, sigpipe_pending, got_epipe)
-#else							/* !ENABLE_THREAD_SAFETY */
+#define RESTORE_SIGPIPE(conn, spinfo) \
+	do { \
+		if (!SIGPIPE_MASKED(conn)) \
+			pq_reset_sigpipe(&(spinfo).oldsigmask, (spinfo).sigpipe_pending, \
+							 (spinfo).got_epipe); \
+	} while (0)
 
-#define DISABLE_SIGPIPE(failaction) \
-	pqsigfunc	oldsighandler = pqsignal(SIGPIPE, SIG_IGN)
+#else /* !ENABLE_THREAD_SAFETY */
 
-#define REMEMBER_EPIPE(cond)
+#define DECLARE_SIGPIPE_INFO(spinfo) pqsigfunc spinfo = NULL
 
-#define RESTORE_SIGPIPE() \
-	pqsignal(SIGPIPE, oldsighandler)
-#endif   /* ENABLE_THREAD_SAFETY */
-#else							/* WIN32 */
+#define DISABLE_SIGPIPE(conn, spinfo, failaction) \
+	do { \
+		if (!SIGPIPE_MASKED(conn)) \
+			spinfo = pqsignal(SIGPIPE, SIG_IGN); \
+	} while (0)
+
+#define REMEMBER_EPIPE(spinfo, cond)
+
+#define RESTORE_SIGPIPE(conn, spinfo) \
+	do { \
+		if (!SIGPIPE_MASKED(conn)) \
+			pqsignal(SIGPIPE, spinfo); \
+	} while (0)
+
+#endif	/* ENABLE_THREAD_SAFETY */
 
-#define DISABLE_SIGPIPE(failaction)
-#define REMEMBER_EPIPE(cond)
-#define RESTORE_SIGPIPE()
-#endif   /* WIN32 */
+#else	/* WIN32 */
+
+#define DECLARE_SIGPIPE_INFO(spinfo)
+#define DISABLE_SIGPIPE(conn, spinfo, failaction)
+#define REMEMBER_EPIPE(spinfo, cond)
+#define RESTORE_SIGPIPE(conn, spinfo)
+
+#endif	/* WIN32 */
 
 /* ------------------------------------------------------------ */
 /*			 Procedures common to all secure sessions			*/
@@ -231,6 +263,9 @@ pqsecure_open_client(PGconn *conn)
 	/* First time through? */
 	if (conn->ssl == NULL)
 	{
+		/* We cannot use MSG_NOSIGNAL to block SIGPIPE when using SSL */
+		conn->sigpipe_flag = false;
+
 		if (!(conn->ssl = SSL_new(SSL_context)) ||
 			!SSL_set_app_data(conn->ssl, conn) ||
 			!SSL_set_fd(conn->ssl, conn->sock))
@@ -283,9 +318,10 @@ pqsecure_read(PGconn *conn, void *ptr, size_t len)
 	if (conn->ssl)
 	{
 		int			err;
+		DECLARE_SIGPIPE_INFO(spinfo);
 
 		/* SSL_read can write to the socket, so we need to disable SIGPIPE */
-		DISABLE_SIGPIPE(return -1);
+		DISABLE_SIGPIPE(conn, spinfo, return -1);
 
 rloop:
 		n = SSL_read(conn->ssl, ptr, len);
@@ -312,7 +348,7 @@ rloop:
 
 					if (n == -1)
 					{
-						REMEMBER_EPIPE(SOCK_ERRNO == EPIPE);
+						REMEMBER_EPIPE(spinfo, SOCK_ERRNO == EPIPE);
 						printfPQExpBuffer(&conn->errorMessage,
 									libpq_gettext("SSL SYSCALL error: %s\n"),
 							SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
@@ -348,7 +384,7 @@ rloop:
 				break;
 		}
 
-		RESTORE_SIGPIPE();
+		RESTORE_SIGPIPE(conn, spinfo);
 	}
 	else
 #endif
@@ -364,14 +400,15 @@ ssize_t
 pqsecure_write(PGconn *conn, const void *ptr, size_t len)
 {
 	ssize_t		n;
-
-	DISABLE_SIGPIPE(return -1);
+	DECLARE_SIGPIPE_INFO(spinfo);
 
 #ifdef USE_SSL
 	if (conn->ssl)
 	{
 		int			err;
 
+		DISABLE_SIGPIPE(conn, spinfo, return -1);
+
 		n = SSL_write(conn->ssl, ptr, len);
 		err = SSL_get_error(conn->ssl, n);
 		switch (err)
@@ -396,7 +433,7 @@ pqsecure_write(PGconn *conn, const void *ptr, size_t len)
 
 					if (n == -1)
 					{
-						REMEMBER_EPIPE(SOCK_ERRNO == EPIPE);
+						REMEMBER_EPIPE(spinfo, SOCK_ERRNO == EPIPE);
 						printfPQExpBuffer(&conn->errorMessage,
 									libpq_gettext("SSL SYSCALL error: %s\n"),
 							SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
@@ -434,11 +471,41 @@ pqsecure_write(PGconn *conn, const void *ptr, size_t len)
 	else
 #endif
 	{
-		n = send(conn->sock, ptr, len, 0);
-		REMEMBER_EPIPE(n < 0 && SOCK_ERRNO == EPIPE);
+		int		flags = 0;
+
+#ifdef MSG_NOSIGNAL
+		if (conn->sigpipe_flag)
+			flags |= MSG_NOSIGNAL;
+
+retry_masked:
+
+#endif /* MSG_NOSIGNAL */
+
+		DISABLE_SIGPIPE(conn, spinfo, return -1);
+
+		n = send(conn->sock, ptr, len, flags);
+
+		if (n < 0)
+		{
+			/*
+			 * If we see an EINVAL, it may be because MSG_NOSIGNAL isn't
+			 * available on this machine.  So, clear sigpipe_flag so we don't
+			 * try the flag again, and retry the send().
+			 */
+#ifdef MSG_NOSIGNAL
+			if (flags != 0 && SOCK_ERRNO == EINVAL)
+			{
+				conn->sigpipe_flag = false;
+				flags = 0;
+				goto retry_masked;
+			}
+#endif /* MSG_NOSIGNAL */
+
+			REMEMBER_EPIPE(spinfo, SOCK_ERRNO == EPIPE);
+		}
 	}
 
-	RESTORE_SIGPIPE();
+	RESTORE_SIGPIPE(conn, spinfo);
 
 	return n;
 }
@@ -1220,14 +1287,16 @@ close_SSL(PGconn *conn)
 {
 	if (conn->ssl)
 	{
-		DISABLE_SIGPIPE((void) 0);
+		DECLARE_SIGPIPE_INFO(spinfo);
+
+		DISABLE_SIGPIPE(conn, spinfo, (void) 0);
 		SSL_shutdown(conn->ssl);
 		SSL_free(conn->ssl);
 		conn->ssl = NULL;
 		pqsecure_destroy();
 		/* We have to assume we got EPIPE */
-		REMEMBER_EPIPE(true);
-		RESTORE_SIGPIPE();
+		REMEMBER_EPIPE(spinfo, true);
+		RESTORE_SIGPIPE(conn, spinfo);
 	}
 
 	if (conn->peer)
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index 51b7128b862c292bddf09c69a559ef28b13efeb8..d93ba4d25e230657863770f23f0f7351827e0293 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -12,7 +12,7 @@
  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/interfaces/libpq/libpq-int.h,v 1.143 2009/06/23 18:13:23 mha Exp $
+ * $PostgreSQL: pgsql/src/interfaces/libpq/libpq-int.h,v 1.144 2009/07/24 17:58:31 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -341,6 +341,8 @@ struct pg_conn
 	ProtocolVersion pversion;	/* FE/BE protocol version in use */
 	int			sversion;		/* server version, e.g. 70401 for 7.4.1 */
 	bool		password_needed;	/* true if server demanded a password */
+	bool		sigpipe_so;		/* have we masked SIGPIPE via SO_NOSIGPIPE? */
+	bool		sigpipe_flag;	/* can we mask SIGPIPE via MSG_NOSIGNAL? */
 
 	/* Transient state needed while establishing connection */
 	struct addrinfo *addrlist;	/* list of possible backend addresses */