diff --git a/src/interfaces/libpq/fe-secure.c b/src/interfaces/libpq/fe-secure.c index 3bb15446269..10bd938981d 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.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 ] @@ -162,6 +162,50 @@ static bool pq_initssllib = true; 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 */ /* ------------------------------------------------------------ */ @@ -268,6 +312,9 @@ pqsecure_read(PGconn *conn, void *ptr, size_t len) { 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); @@ -292,9 +339,12 @@ rloop: 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, @@ -325,6 +375,8 @@ rloop: n = -1; break; } + + RESTORE_SIGPIPE(); } else #endif @@ -341,19 +393,7 @@ pqsecure_write(PGconn *conn, const void *ptr, size_t len) { 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) @@ -384,10 +424,7 @@ pqsecure_write(PGconn *conn, const void *ptr, size_t len) 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))); @@ -426,19 +463,10 @@ pqsecure_write(PGconn *conn, const void *ptr, size_t len) #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; } @@ -1092,9 +1120,13 @@ close_SSL(PGconn *conn) { 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) @@ -1167,6 +1199,7 @@ PQgetssl(PGconn *conn) } #endif /* USE_SSL */ + #if defined(ENABLE_THREAD_SAFETY) && !defined(WIN32) /* @@ -1251,4 +1284,4 @@ pq_reset_sigpipe(sigset_t *osigset, bool sigpipe_pending, bool got_epipe) SOCK_ERRNO_SET(save_errno); } -#endif /* ENABLE_THREAD_SAFETY */ +#endif /* ENABLE_THREAD_SAFETY && !WIN32 */