aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKazuki Yamaguchi <k@rhe.jp>2018-10-22 10:26:33 +0900
committerKazuki Yamaguchi <k@rhe.jp>2020-08-12 20:26:03 +0900
commit2e700c80bfab1b2668174a207588301cbfbdcd3d (patch)
tree4e79cd44c341b12bd7dc81171638f15fa8a6a74f
parentad24cc35e8819041195401c09d73d6c71898ec73 (diff)
downloadruby-openssl-ky/ssl-macos-send-eprototype.tar.gz
ssl: retry write on EPROTOTYPE on macOSky/ssl-macos-send-eprototype
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
-rw-r--r--ext/openssl/ossl_ssl.c15
1 files changed, 15 insertions, 0 deletions
diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c
index 3e38bd13..29e7b1d6 100644
--- a/ext/openssl/ossl_ssl.c
+++ b/ext/openssl/ossl_ssl.c
@@ -1685,6 +1685,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)
@@ -1975,6 +1980,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");