[ruby/openssl] ssl: retry write on EPROTOTYPE on macOS

Errno::EPROTOTYPE is not supposed to be raised by SSLSocket#write.
However, on macOS, send(2) which is called via SSL_write() can
occasionally return EPROTOTYPE. Retry SSL_write() so that we get a
proper error, just as ext/socket does.

Reference: https://bugs.ruby-lang.org/issues/14713
Reference: https://github.com/ruby/openssl/issues/227

https://github.com/ruby/openssl/commit/2e700c80bf
This commit is contained in:
Kazuki Yamaguchi 2018-10-22 10:26:33 +09:00
parent 0b1bb1bc32
commit 945ed40862
Notes: git 2021-03-16 20:38:43 +09:00

View File

@ -1691,6 +1691,11 @@ ossl_start_ssl(VALUE self, int (*func)(), const char *funcname, VALUE opts)
rb_io_wait_readable(fptr->fd);
continue;
case SSL_ERROR_SYSCALL:
#ifdef __APPLE__
/* See ossl_ssl_write_internal() */
if (errno == EPROTOTYPE)
continue;
#endif
if (errno) rb_sys_fail(funcname);
ossl_raise(eSSLError, "%s SYSCALL returned=%d errno=%d state=%s", funcname, ret2, errno, SSL_state_string_long(ssl));
#if defined(SSL_R_CERTIFICATE_VERIFY_FAILED)
@ -1982,6 +1987,16 @@ ossl_ssl_write_internal(VALUE self, VALUE str, VALUE opts)
rb_io_wait_readable(fptr->fd);
continue;
case SSL_ERROR_SYSCALL:
#ifdef __APPLE__
/*
* It appears that send syscall can return EPROTOTYPE if the
* socket is being torn down. Retry to get a proper errno to
* make the error handling in line with the socket library.
* [Bug #14713] https://bugs.ruby-lang.org/issues/14713
*/
if (errno == EPROTOTYPE)
continue;
#endif
if (errno) rb_sys_fail(0);
default:
ossl_raise(eSSLError, "SSL_write");