]> granicus.if.org Git - postgresql/commitdiff
Clear retry flags properly in replacement OpenSSL sock_write function.
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 5 Dec 2013 17:48:35 +0000 (12:48 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 5 Dec 2013 17:48:35 +0000 (12:48 -0500)
Current OpenSSL code includes a BIO_clear_retry_flags() step in the
sock_write() function.  Either we failed to copy the code correctly, or
they added this since we copied it.  In any case, lack of the clear step
appears to be the cause of the server lockup after connection loss reported
in bug #8647 from Valentine Gogichashvili.  Assume that this is correct
coding for all OpenSSL versions, and hence back-patch to all supported
branches.

Diagnosis and patch by Alexander Kukushkin.

src/backend/libpq/be-secure.c

index e0ab5997fbd9337d07a38e6fe79b7f144c6d6d04..f52ca3e6e3e3d4bcef0c37d8e30aedc6a7684a06 100644 (file)
@@ -411,7 +411,10 @@ wloop:
  * non-reentrant libc facilities. We also need to call send() and recv()
  * directly so it gets passed through the socket/signals layer on Win32.
  *
- * They are closely modelled on the original socket implementations in OpenSSL.
+ * These functions are closely modelled on the standard socket BIO in OpenSSL;
+ * see sock_read() and sock_write() in OpenSSL's crypto/bio/bss_sock.c.
+ * XXX OpenSSL 1.0.1e considers many more errcodes than just EINTR as reasons
+ * to retry; do we need to adopt their logic for that?
  */
 
 static bool my_bio_initialized = false;
@@ -449,6 +452,7 @@ my_sock_write(BIO *h, const char *buf, int size)
        int                     res = 0;
 
        res = send(h->num, buf, size, 0);
+       BIO_clear_retry_flags(h);
        if (res <= 0)
        {
                if (errno == EINTR)