*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.101 2008/01/01 19:46:00 momjian Exp $
+ * $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.102 2008/01/29 02:03:39 tgl Exp $
*
* NOTES
* [ Most of these notes are wrong/obsolete, but perhaps not all ]
static SSL_CTX *SSL_context = NULL;
#endif
+/*
+ * Macros to handle disabling and then restoring the state of SIGPIPE handling.
+ * Note that DISABLE_SIGPIPE() must appear at the start of a block.
+ */
+
+#ifndef WIN32
+#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
+
+#define REMEMBER_EPIPE(cond) \
+ do { \
+ if (cond) \
+ got_epipe = true; \
+ } while (0)
+
+#define RESTORE_SIGPIPE() \
+ pq_reset_sigpipe(&osigmask, sigpipe_pending, got_epipe)
+
+#else /* !ENABLE_THREAD_SAFETY */
+
+#define DISABLE_SIGPIPE(failaction) \
+ pqsigfunc oldsighandler = pqsignal(SIGPIPE, SIG_IGN)
+
+#define REMEMBER_EPIPE(cond)
+
+#define RESTORE_SIGPIPE() \
+ pqsignal(SIGPIPE, oldsighandler)
+
+#endif /* ENABLE_THREAD_SAFETY */
+#else /* WIN32 */
+
+#define DISABLE_SIGPIPE(failaction)
+#define REMEMBER_EPIPE(cond)
+#define RESTORE_SIGPIPE()
+
+#endif /* WIN32 */
+
/* ------------------------------------------------------------ */
/* Procedures common to all secure sessions */
/* ------------------------------------------------------------ */
{
int err;
+ /* SSL_read can write to the socket, so we need to disable SIGPIPE */
+ DISABLE_SIGPIPE(return -1);
+
rloop:
n = SSL_read(conn->ssl, ptr, len);
err = SSL_get_error(conn->ssl, n);
char sebuf[256];
if (n == -1)
+ {
+ REMEMBER_EPIPE(SOCK_ERRNO == EPIPE);
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSL SYSCALL error: %s\n"),
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
+ }
else
{
printfPQExpBuffer(&conn->errorMessage,
n = -1;
break;
}
+
+ RESTORE_SIGPIPE();
}
else
#endif
{
ssize_t n;
-#ifndef WIN32
-#ifdef ENABLE_THREAD_SAFETY
- sigset_t osigmask;
- bool sigpipe_pending;
- bool got_epipe = false;
-
-
- if (pq_block_sigpipe(&osigmask, &sigpipe_pending) < 0)
- return -1;
-#else
- pqsigfunc oldsighandler = pqsignal(SIGPIPE, SIG_IGN);
-#endif /* ENABLE_THREAD_SAFETY */
-#endif /* WIN32 */
+ DISABLE_SIGPIPE(return -1);
#ifdef USE_SSL
if (conn->ssl)
if (n == -1)
{
-#if defined(ENABLE_THREAD_SAFETY) && !defined(WIN32)
- if (SOCK_ERRNO == EPIPE)
- got_epipe = true;
-#endif
+ REMEMBER_EPIPE(SOCK_ERRNO == EPIPE);
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSL SYSCALL error: %s\n"),
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
#endif
{
n = send(conn->sock, ptr, len, 0);
-#if defined(ENABLE_THREAD_SAFETY) && !defined(WIN32)
- if (n < 0 && SOCK_ERRNO == EPIPE)
- got_epipe = true;
-#endif
+ REMEMBER_EPIPE(n < 0 && SOCK_ERRNO == EPIPE);
}
-#ifndef WIN32
-#ifdef ENABLE_THREAD_SAFETY
- pq_reset_sigpipe(&osigmask, sigpipe_pending, got_epipe);
-#else
- pqsignal(SIGPIPE, oldsighandler);
-#endif /* ENABLE_THREAD_SAFETY */
-#endif /* WIN32 */
+ RESTORE_SIGPIPE();
return n;
}
{
if (conn->ssl)
{
+ DISABLE_SIGPIPE((void) 0);
SSL_shutdown(conn->ssl);
SSL_free(conn->ssl);
conn->ssl = NULL;
+ /* We have to assume we got EPIPE */
+ REMEMBER_EPIPE(true);
+ RESTORE_SIGPIPE();
}
if (conn->peer)
}
#endif /* USE_SSL */
+
#if defined(ENABLE_THREAD_SAFETY) && !defined(WIN32)
/*
SOCK_ERRNO_SET(save_errno);
}
-#endif /* ENABLE_THREAD_SAFETY */
+#endif /* ENABLE_THREAD_SAFETY && !WIN32 */