Fix poor errno handling in libpq's version of our custom OpenSSL BIO.
authorTom Lane <[email protected]>
Mon, 28 Sep 2015 22:02:38 +0000 (18:02 -0400)
committerTom Lane <[email protected]>
Mon, 28 Sep 2015 22:02:38 +0000 (18:02 -0400)
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.)

src/interfaces/libpq/fe-secure-openssl.c

index d4069b9e0bd9c226346776e9362af07fec71cd8b..4b2a324634bbefc42941772bfcec625f78b80c58 100644 (file)
@@ -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;
        }
    }