summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornagachika <nagachika@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-07-02 09:15:33 +0000
committernagachika <nagachika@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-07-02 09:15:33 +0000
commitfcb4a3d88fa38589239281b1b670b95fba47b277 (patch)
tree0d8ebfab3a5c757ad26df8cfbc0a57ada506a404
parent4a625f839ccd9f226fcef95499c4b48702cc0b69 (diff)
merge revision(s) 63304: [Backport #14713]
io.c: workaround for EPROTOTYPE * io.c (internal_write_func, internal_writev_func): retry at unexpected EPROTOTYPE on macOS, to get rid of a kernel bug. [ruby-core:86690] [Bug #14713] * ext/socket/init.c (rsock_{sendto,send,write}_blocking): ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_5@63826 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ext/socket/init.c26
-rw-r--r--io.c13
-rw-r--r--test/net/ftp/test_ftp.rb2
-rw-r--r--version.h2
4 files changed, 35 insertions, 8 deletions
diff --git a/ext/socket/init.c b/ext/socket/init.c
index 189977dcba..e357beb0c9 100644
--- a/ext/socket/init.c
+++ b/ext/socket/init.c
@@ -56,6 +56,12 @@ is_socket(int fd)
}
#endif
+#if defined __APPLE__
+# define do_write_retry(code) do {ret = code;} while (ret == -1 && errno == EPROTOTYPE)
+#else
+# define do_write_retry(code) ret = code
+#endif
+
VALUE
rsock_init_sock(VALUE sock, int fd)
{
@@ -83,8 +89,10 @@ rsock_sendto_blocking(void *data)
{
struct rsock_send_arg *arg = data;
VALUE mesg = arg->mesg;
- return (VALUE)sendto(arg->fd, RSTRING_PTR(mesg), RSTRING_LEN(mesg),
- arg->flags, arg->to, arg->tolen);
+ ssize_t ret;
+ do_write_retry(sendto(arg->fd, RSTRING_PTR(mesg), RSTRING_LEN(mesg),
+ arg->flags, arg->to, arg->tolen));
+ return (VALUE)ret;
}
VALUE
@@ -92,8 +100,10 @@ rsock_send_blocking(void *data)
{
struct rsock_send_arg *arg = data;
VALUE mesg = arg->mesg;
- return (VALUE)send(arg->fd, RSTRING_PTR(mesg), RSTRING_LEN(mesg),
- arg->flags);
+ ssize_t ret;
+ do_write_retry(send(arg->fd, RSTRING_PTR(mesg), RSTRING_LEN(mesg),
+ arg->flags));
+ return (VALUE)ret;
}
struct recvfrom_arg {
@@ -366,10 +376,18 @@ rsock_write_nonblock(VALUE sock, VALUE str, VALUE ex)
rb_io_flush(sock);
}
+#ifdef __APPLE__
+ again:
+#endif
n = (long)send(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str), MSG_DONTWAIT);
if (n < 0) {
int e = errno;
+#ifdef __APPLE__
+ if (e == EPROTOTYPE) {
+ goto again;
+ }
+#endif
if (e == EWOULDBLOCK || e == EAGAIN) {
if (ex == Qfalse) return sym_wait_writable;
rb_readwrite_syserr_fail(RB_IO_WAIT_WRITABLE, e,
diff --git a/io.c b/io.c
index f14e1440ca..f14080e21e 100644
--- a/io.c
+++ b/io.c
@@ -937,11 +937,18 @@ internal_read_func(void *ptr)
return read(iis->fd, iis->buf, iis->capa);
}
+#if defined __APPLE__
+# define do_write_retry(code) do {ret = code;} while (ret == -1 && errno == EPROTOTYPE)
+#else
+# define do_write_retry(code) ret = code
+#endif
static VALUE
internal_write_func(void *ptr)
{
struct io_internal_write_struct *iis = ptr;
- return write(iis->fd, iis->buf, iis->capa);
+ ssize_t ret;
+ do_write_retry(write(iis->fd, iis->buf, iis->capa));
+ return (VALUE)ret;
}
static void*
@@ -956,7 +963,9 @@ static VALUE
internal_writev_func(void *ptr)
{
struct io_internal_writev_struct *iis = ptr;
- return writev(iis->fd, iis->iov, iis->iovcnt);
+ ssize_t ret;
+ do_write_retry(writev(iis->fd, iis->iov, iis->iovcnt));
+ return (VALUE)ret;
}
#endif
diff --git a/test/net/ftp/test_ftp.rb b/test/net/ftp/test_ftp.rb
index 461ba1630e..03204ebc52 100644
--- a/test/net/ftp/test_ftp.rb
+++ b/test/net/ftp/test_ftp.rb
@@ -425,7 +425,7 @@ class FTPTest < Test::Unit::TestCase
end
conn.print(l, "\r\n")
end
- rescue Errno::EPIPE, Errno::EPROTOTYPE
+ rescue Errno::EPIPE
ensure
assert_nil($!)
conn.close
diff --git a/version.h b/version.h
index 962ac03dc8..f3f711db1c 100644
--- a/version.h
+++ b/version.h
@@ -1,6 +1,6 @@
#define RUBY_VERSION "2.5.2"
#define RUBY_RELEASE_DATE "2018-07-02"
-#define RUBY_PATCHLEVEL 64
+#define RUBY_PATCHLEVEL 65
#define RUBY_RELEASE_YEAR 2018
#define RUBY_RELEASE_MONTH 7