Skip to content

Commit

Permalink
merge revision(s) 63304: [Backport #14713]
Browse files Browse the repository at this point in the history
	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
  • Loading branch information
nagachika authored and tenderlove committed Jul 12, 2018
1 parent 8ddeafe commit 7322945
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 8 deletions.
26 changes: 22 additions & 4 deletions ext/socket/init.c
Expand Up @@ -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)
{
Expand Down Expand Up @@ -83,17 +89,21 @@ 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
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 {
Expand Down Expand Up @@ -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,
Expand Down
13 changes: 11 additions & 2 deletions io.c
Expand Up @@ -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*
Expand All @@ -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

Expand Down
2 changes: 1 addition & 1 deletion test/net/ftp/test_ftp.rb
Expand Up @@ -425,7 +425,7 @@ def test_list_read_timeout_exceeded
end
conn.print(l, "\r\n")
end
rescue Errno::EPIPE, Errno::EPROTOTYPE
rescue Errno::EPIPE
ensure
assert_nil($!)
conn.close
Expand Down
2 changes: 1 addition & 1 deletion 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
Expand Down

0 comments on commit 7322945

Please sign in to comment.