summaryrefslogtreecommitdiff
path: root/ext/socket
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-04-30 02:17:03 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-04-30 02:17:03 +0000
commit7727b22eb1dd2aab3127a0b4fdb6ee52aedf358e (patch)
tree5f0dd96fe72ce2fc777e77425582f361b1f19f6d /ext/socket
parent9cd4834810f4cb3bf093f07666e4cba0a2a66f94 (diff)
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/trunk@63304 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext/socket')
-rw-r--r--ext/socket/init.c26
1 files changed, 22 insertions, 4 deletions
diff --git a/ext/socket/init.c b/ext/socket/init.c
index 3b22c1308b..c26ab135ab 100644
--- a/ext/socket/init.c
+++ b/ext/socket/init.c
@@ -68,6 +68,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)
{
@@ -95,8 +101,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
@@ -104,8 +112,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 {
@@ -378,10 +388,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,