]> granicus.if.org Git - postgresql/commitdiff
Fix poor errno handling in libpq's version of our custom OpenSSL BIO.
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 28 Sep 2015 22:02:38 +0000 (18:02 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
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;
                }
        }