fi
 HAVE_POSIX_SIGNALS=$pgac_cv_func_posix_signals
 
+if test "$pgac_cv_func_posix_signals" != yes -a "$enable_thread_safety" = yes; then
+  { { echo "$as_me:$LINENO: error:
+*** Thread-safety requires POSIX signals, which are not supported by your
+*** operating system.
+" >&5
+echo "$as_me: error:
+*** Thread-safety requires POSIX signals, which are not supported by your
+*** operating system.
+" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
 if test $ac_cv_func_fseeko = yes; then
 # Check whether --enable-largefile or --disable-largefile was given.
 if test "${enable_largefile+set}" = set; then
 
 dnl Process this file with autoconf to produce a configure script.
-dnl $PostgreSQL: pgsql/configure.in,v 1.387 2004/11/30 06:13:04 tgl Exp $
+dnl $PostgreSQL: pgsql/configure.in,v 1.388 2004/12/02 15:32:50 momjian Exp $
 dnl
 dnl Developers, please strive to achieve this order:
 dnl
 
 
 PGAC_FUNC_POSIX_SIGNALS
+if test "$pgac_cv_func_posix_signals" != yes -a "$enable_thread_safety" = yes; then
+  AC_MSG_ERROR([
+*** Thread-safety requires POSIX signals, which are not supported by your
+*** operating system.
+])
+fi
+
 if test $ac_cv_func_fseeko = yes; then
 AC_SYS_LARGEFILE
 fi
 
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.169 2004/11/27 21:56:04 petere Exp $
+$PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.170 2004/12/02 15:32:52 momjian Exp $
 -->
 
  <chapter id="libpq">
 which is thread-safe on all platforms.
 </para>
 
-<para>
-<application>libpq</application> must ignore <literal>SIGPIPE</> signals
-generated internally by <function>send()</> calls to backend processes.
-When <productname>PostgreSQL</> is configured without
-<literal>--enable-thread-safety</>, <application>libpq</> sets
-<literal>SIGPIPE</> to <literal>SIG_IGN</> before each
-<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.  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
-<function>PQinSend()</> to determine if it should ignore the
-<literal>SIGPIPE</> signal. This function is available in both
-thread-safe and non-thread-safe versions of <application>libpq</>.
-</para>
-
 <para>
 If you experience problems with threaded applications, run
 the program in <filename>src/tools/thread</> to see if your
 
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/copy.sgml,v 1.60 2004/11/27 21:56:05 petere Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/copy.sgml,v 1.61 2004/12/02 15:32:53 momjian Exp $
 PostgreSQL documentation
 -->
 
+
 <refentry id="SQL-COPY">
  <refmeta>
   <refentrytitle id="sql-copy-title">COPY</refentrytitle>
 
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.290 2004/12/01 23:42:26 momjian Exp $
+ *   $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.291 2004/12/02 15:32:54 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
    const char *node = NULL;
    int         ret;
 
-#ifdef ENABLE_THREAD_SAFETY
-#ifndef WIN32
-   static pthread_once_t check_sigpipe_once = PTHREAD_ONCE_INIT;
-
-   /* Check only on first connection request */
-   pthread_once(&check_sigpipe_once, pq_check_sigpipe_handler);
-#endif
-#endif
-
    if (!conn)
        return 0;
 
 
  * didn't really belong there.
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/interfaces/libpq/fe-print.c,v 1.55 2004/11/09 15:57:57 petere Exp $
+ *   $PostgreSQL: pgsql/src/interfaces/libpq/fe-print.c,v 1.56 2004/12/02 15:32:54 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
        int         total_line_length = 0;
        int         usePipe = 0;
        char       *pagerenv;
-
+#ifdef ENABLE_THREAD_SAFETY
+       sigset_t    osigset;
+       bool        sigpipe_masked = false;
+       bool        sigpipe_pending;
+#endif
 #if !defined(ENABLE_THREAD_SAFETY) && !defined(WIN32)
        pqsigfunc   oldsigpipehandler = NULL;
 #endif
                {
                    usePipe = 1;
 #ifdef ENABLE_THREAD_SAFETY
-                   pthread_setspecific(pq_thread_in_send, "t");
+                   pq_block_sigpipe(&osigset, &sigpipe_pending);
+                   sigpipe_masked = true;
 #else
 #ifndef WIN32
                    oldsigpipehandler = pqsignal(SIGPIPE, SIG_IGN);
            pclose(fout);
 #endif
 #ifdef ENABLE_THREAD_SAFETY
-           pthread_setspecific(pq_thread_in_send, "f");
+           if (sigpipe_masked)
+               pq_reset_sigpipe(&osigset, sigpipe_pending);
 #else
 #ifndef WIN32
            pqsignal(SIGPIPE, oldsigpipehandler);
 
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.57 2004/11/20 00:35:13 tgl Exp $
+ *   $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.58 2004/12/02 15:32:54 momjian Exp $
  *
  * NOTES
  *   [ Most of these notes are wrong/obsolete, but perhaps not all ]
 static SSL_CTX *SSL_context = NULL;
 #endif
 
-#ifdef ENABLE_THREAD_SAFETY
-static void sigpipe_handler_ignore_send(int signo);
-pthread_key_t pq_thread_in_send = 0;   /* initializer needed on Darwin */
-static pqsigfunc pq_pipe_handler;
-#endif
-
 /* ------------------------------------------------------------ */
 /*                      Hardcoded values                       */
 /* ------------------------------------------------------------ */
 pqsecure_write(PGconn *conn, const void *ptr, size_t len)
 {
    ssize_t     n;
-
+   
 #ifdef ENABLE_THREAD_SAFETY
-   pthread_setspecific(pq_thread_in_send, "t");
+   sigset_t    osigmask;
+   bool        sigpipe_pending;
+   
+   pq_block_sigpipe(&osigmask, &sigpipe_pending);
 #else
 #ifndef WIN32
    pqsigfunc   oldsighandler = pqsignal(SIGPIPE, SIG_IGN);
    else
 #endif
        n = send(conn->sock, ptr, len, 0);
+       /*
+        *  Possible optimization:  if sigpending() turns out to be an
+        *  expensive operation, we can set sigpipe_pending = 'true'
+        *  here if errno != EPIPE, avoiding a sigpending call.
+        */
 
 #ifdef ENABLE_THREAD_SAFETY
-   pthread_setspecific(pq_thread_in_send, "f");
+   pq_reset_sigpipe(&osigmask, sigpipe_pending);
 #else
 #ifndef WIN32
    pqsignal(SIGPIPE, oldsighandler);
 }
 #endif   /* USE_SSL */
 
-
 #ifdef ENABLE_THREAD_SAFETY
-#ifndef WIN32
 /*
- * Check SIGPIPE handler and perhaps install our own.
+ * Block SIGPIPE for this thread.  This prevents send()/write() from exiting
+ * the application.
  */
-void
-pq_check_sigpipe_handler(void)
-{
-   pthread_key_create(&pq_thread_in_send, NULL);
-
-   /*
-    * Find current pipe handler and chain on to it.
-    */
-   pq_pipe_handler = pqsignalinquire(SIGPIPE);
-   pqsignal(SIGPIPE, sigpipe_handler_ignore_send);
-}
-
-/*
- * Threaded SIGPIPE signal handler
- */
-void
-sigpipe_handler_ignore_send(int signo)
+int
+pq_block_sigpipe(sigset_t *osigset, bool *sigpipe_pending)
 {
-   /*
-    * 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())
+   sigset_t sigpipe_sigset;
+   sigset_t sigset;
+   int      ret;
+   
+   sigemptyset(&sigpipe_sigset);
+   sigaddset(&sigpipe_sigset, SIGPIPE);
+
+   /* Block SIGPIPE and save previous mask for later reset */
+   ret = pthread_sigmask(SIG_BLOCK, &sigpipe_sigset, osigset);
+
+   /* We can have a pending SIGPIPE only if it was blocked before */
+   if (sigismember(osigset, SIGPIPE))
    {
-       if (pq_pipe_handler == SIG_DFL) /* not set by application */
-           exit(128 + SIGPIPE);    /* typical return value for SIG_DFL */
+       /* Is there a pending SIGPIPE? */
+       if (sigpending(&sigset) != 0)
+           return -1;
+   
+       if (sigismember(&sigset, SIGPIPE))
+           *sigpipe_pending = true;
        else
-           (*pq_pipe_handler) (signo); /* call original handler */
+           *sigpipe_pending = false;
    }
+   else
+       *sigpipe_pending = false;
+   
+   return ret;
 }
-#endif
-#endif
-
+   
 /*
- * Indicates whether the current thread is in send()
- * For use by SIGPIPE signal handlers;  they should
- * ignore SIGPIPE when libpq is in send().  This means
- * that the backend has died unexpectedly.
+ * Discard any pending SIGPIPE and reset the signal mask.
+ * We might be discarding a blocked SIGPIPE that we didn't generate,
+ * but we document that you can't keep blocked SIGPIPE calls across
+ * libpq function calls.
  */
-pqbool
-PQinSend(void)
+int
+pq_reset_sigpipe(sigset_t *osigset, bool sigpipe_pending)
 {
-#ifdef ENABLE_THREAD_SAFETY
-   return (pthread_getspecific(pq_thread_in_send) /* has it been set? */ &&
-           *(char *) pthread_getspecific(pq_thread_in_send) == 't') ? true : false;
-#else
+   int signo;
+   sigset_t sigset;
 
-   /*
-    * No threading: our code ignores SIGPIPE around send(). Therefore, we
-    * can't be in send() if we are checking from a SIGPIPE signal
-    * handler.
-    */
-   return false;
-#endif
+   /* Clear SIGPIPE only if none was pending */
+   if (!sigpipe_pending)
+   {
+       if (sigpending(&sigset) != 0)
+           return -1;
+   
+       /*
+        *  Discard pending and blocked SIGPIPE
+        */
+       if (sigismember(&sigset, SIGPIPE))
+       {
+           sigset_t sigpipe_sigset;
+           
+           sigemptyset(&sigpipe_sigset);
+           sigaddset(&sigpipe_sigset, SIGPIPE);
+   
+           sigwait(&sigpipe_sigset, &signo);
+           if (signo != SIGPIPE)
+               return -1;
+       }
+   }
+   
+   /* Restore saved block mask */
+   return pthread_sigmask(SIG_SETMASK, osigset, NULL);
 }
+#endif
 
  * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/interfaces/libpq/libpq-fe.h,v 1.113 2004/10/30 23:11:27 tgl Exp $
+ * $PostgreSQL: pgsql/src/interfaces/libpq/libpq-fe.h,v 1.114 2004/12/02 15:32:54 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 /* === in fe-secure.c === */
 
-/*
- * Indicates whether the libpq thread is in send().
- * Used to ignore SIGPIPE if thread is in send().
- */
-extern pqbool PQinSend(void);
-
 #ifdef __cplusplus
 }
 #endif
 
  * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/interfaces/libpq/libpq-int.h,v 1.96 2004/10/30 23:11:27 tgl Exp $
+ * $PostgreSQL: pgsql/src/interfaces/libpq/libpq-int.h,v 1.97 2004/12/02 15:32:54 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 #ifdef ENABLE_THREAD_SAFETY
 #include <pthread.h>
+#include <signal.h>
 #endif
 
 #ifdef WIN32_CLIENT_ONLY
 extern ssize_t pqsecure_read(PGconn *, void *ptr, size_t len);
 extern ssize_t pqsecure_write(PGconn *, const void *ptr, size_t len);
 
-#ifdef ENABLE_THREAD_SAFETY
-extern void pq_check_sigpipe_handler(void);
-extern pthread_key_t pq_thread_in_send;
-#endif
-
 #ifdef USE_SSL
 extern bool pq_initssllib;
 #endif
 
+#ifdef ENABLE_THREAD_SAFETY
+int pq_block_sigpipe(sigset_t *osigset, bool *sigpipe_pending);
+int pq_reset_sigpipe(sigset_t *osigset, bool sigpipe_pending);
+#endif
+
 /*
  * this is so that we can check if a connection is non-blocking internally
  * without the overhead of a function call