From: Tom Lane Date: Mon, 28 Sep 2015 22:02:38 +0000 (-0400) Subject: Fix poor errno handling in libpq's version of our custom OpenSSL BIO. X-Git-Tag: REL9_6_BETA1~1302 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=60f1e6bc130241c1f1da337d0a08a05ee8b982d8;p=postgresql Fix poor errno handling in libpq's version of our custom OpenSSL BIO. Thom Brown reported that SSL connections didn't seem to work on Windows in 9.5. Asif Naeem figured out that the cause was my_sock_read() looking at "errno" when it needs to look at "SOCK_ERRNO". This mistake was introduced in commit 680513ab79c7e12e402a2aad7921b95a25a4bcc8, which cloned the backend's custom SSL BIO code into libpq, and didn't translate the errno handling properly. Moreover, it introduced unnecessary errno save/restore logic, which was particularly confusing because it was incomplete; and it failed to check for all three of EINTR, EAGAIN, and EWOULDBLOCK in my_sock_write. (That might not be necessary; but since we're copying well-tested backend code that does do that, it seems prudent to copy it faithfully.) --- diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c index d4069b9e0b..4b2a324634 100644 --- a/src/interfaces/libpq/fe-secure-openssl.c +++ b/src/interfaces/libpq/fe-secure-openssl.c @@ -1598,14 +1598,13 @@ static int my_sock_read(BIO *h, char *buf, int size) { int res; - int save_errno; res = pqsecure_raw_read((PGconn *) h->ptr, buf, size); - save_errno = errno; BIO_clear_retry_flags(h); if (res < 0) { - switch (save_errno) + /* If we were interrupted, tell caller to retry */ + switch (SOCK_ERRNO) { #ifdef EAGAIN case EAGAIN: @@ -1622,7 +1621,6 @@ my_sock_read(BIO *h, char *buf, int size) } } - errno = save_errno; return res; } @@ -1630,16 +1628,26 @@ static int my_sock_write(BIO *h, const char *buf, int size) { int res; - int save_errno; res = pqsecure_raw_write((PGconn *) h->ptr, buf, size); - save_errno = errno; BIO_clear_retry_flags(h); if (res <= 0) { - if (save_errno == EINTR) + /* If we were interrupted, tell caller to retry */ + switch (SOCK_ERRNO) { - BIO_set_retry_write(h); +#ifdef EAGAIN + case EAGAIN: +#endif +#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN)) + case EWOULDBLOCK: +#endif + case EINTR: + BIO_set_retry_write(h); + break; + + default: + break; } }