aboutsummaryrefslogtreecommitdiff
path: root/src/interfaces/libpq/fe-secure.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/interfaces/libpq/fe-secure.c')
-rw-r--r--src/interfaces/libpq/fe-secure.c75
1 files changed, 74 insertions, 1 deletions
diff --git a/src/interfaces/libpq/fe-secure.c b/src/interfaces/libpq/fe-secure.c
index 34f94b0ad07..e650b6b275e 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.34 2003/12/18 22:49:26 tgl Exp $
+ * $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.35 2004/01/09 02:02:43 momjian Exp $
*
* NOTES
* The client *requires* a valid server certificate. Since
@@ -106,6 +106,10 @@
#include <arpa/inet.h>
#endif
+#ifdef ENABLE_THREAD_SAFETY
+#include <pthread.h>
+#endif
+
#ifndef HAVE_STRDUP
#include "strdup.h"
#endif
@@ -142,6 +146,11 @@ static const char *SSLerrmessage(void);
static SSL_CTX *SSL_context = NULL;
#endif
+#ifdef ENABLE_THREAD_SAFETY
+static void sigpipe_handler_ignore_send(int signo);
+pthread_key_t thread_in_send;
+#endif
+
/* ------------------------------------------------------------ */
/* Hardcoded values */
/* ------------------------------------------------------------ */
@@ -347,9 +356,13 @@ pqsecure_write(PGconn *conn, const void *ptr, size_t len)
{
ssize_t n;
+#ifdef ENABLE_THREAD_SAFETY
+ pthread_setspecific(thread_in_send, "t");
+#else
#ifndef WIN32
pqsigfunc oldsighandler = pqsignal(SIGPIPE, SIG_IGN);
#endif
+#endif
#ifdef USE_SSL
if (conn->ssl)
@@ -407,9 +420,13 @@ pqsecure_write(PGconn *conn, const void *ptr, size_t len)
#endif
n = send(conn->sock, ptr, len, 0);
+#ifdef ENABLE_THREAD_SAFETY
+ pthread_setspecific(thread_in_send, "f");
+#else
#ifndef WIN32
pqsignal(SIGPIPE, oldsighandler);
#endif
+#endif
return n;
}
@@ -1048,3 +1065,59 @@ PQgetssl(PGconn *conn)
}
#endif /* USE_SSL */
+
+
+#ifdef ENABLE_THREAD_SAFETY
+/*
+ * Check SIGPIPE handler and perhaps install our own.
+ */
+void
+check_sigpipe_handler(void)
+{
+ pqsigfunc pipehandler;
+
+ /*
+ * 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.
+ */
+ 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(&thread_in_send, NULL);
+ pqsignal(SIGPIPE, sigpipe_handler_ignore_send);
+ }
+}
+
+/*
+ * Threaded SIGPIPE signal handler
+ */
+void
+sigpipe_handler_ignore_send(int signo)
+{
+ /* If we have gotten a SIGPIPE outside send(), exit */
+ if (!PQinSend())
+ exit(128 + SIGPIPE); /* typical return value for SIG_DFL */
+}
+#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.
+ */
+pqbool
+PQinSend(void)
+{
+#ifdef ENABLE_THREAD_SAFETY
+ return (pthread_getspecific(thread_in_send) /* has it been set? */ &&
+ *(char *)pthread_getspecific(thread_in_send) == 't') ? true : false;
+#else
+ return false; /* No threading, so we can't be in send() */
+#endif
+}