diff options
author | naruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2014-02-20 04:44:35 +0000 |
---|---|---|
committer | naruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2014-02-20 04:44:35 +0000 |
commit | 6770402812366dac38469876c7493c9e3ab71ffe (patch) | |
tree | c754d5218d50c6182c0d0f0efa787870e2cad036 /process.c | |
parent | f851d5dea640be815df95f7f4525c0045eb278f1 (diff) |
merge revision(s) 44687,44706,44727: [Backport #8770]
* process.c (recv_child_error): Fix deadlock in rb_fork_internal when a
signal is sent to the parent process while Ruby is forking in IO.popen.
Patch by Scott Francis. Closes GH-513.
* process.c (send_child_error): retry write on EINTR to fix
occasional Errno::EINTR from Process.spawn.
* process.c (recv_child_error): retry read on EINTR to fix
occasional Errno::EINTR from Process.spawn.
* process.c (READ_FROM_CHILD): Apply the last hunk of
0001-process.c-avoid-EINTR-from-Process.spawn.patch written by
Eric Wong in [Bug #8770].
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_1@45061 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'process.c')
-rw-r--r-- | process.c | 34 |
1 files changed, 29 insertions, 5 deletions
@@ -3296,6 +3296,30 @@ retry_fork(int *status, int *ep, int chfunc_is_async_signal_safe) } } +static ssize_t +write_retry(int fd, const void *buf, size_t len) +{ + ssize_t w; + + do { + w = write(fd, buf, len); + } while (w < 0 && errno == EINTR); + + return w; +} + +static ssize_t +read_retry(int fd, void *buf, size_t len) +{ + ssize_t r; + + do { + r = read(fd, buf, len); + } while (r < 0 && errno == EINTR); + + return r; +} + static void send_child_error(int fd, int state, char *errmsg, size_t errmsg_buflen, int chfunc_is_async_signal_safe) { @@ -3303,7 +3327,7 @@ send_child_error(int fd, int state, char *errmsg, size_t errmsg_buflen, int chfu int err; if (!chfunc_is_async_signal_safe) { - if (write(fd, &state, sizeof(state)) == sizeof(state) && state) { + if (write_retry(fd, &state, sizeof(state)) == sizeof(state) && state) { VALUE errinfo = rb_errinfo(); io = rb_io_fdopen(fd, O_WRONLY|O_BINARY, NULL); rb_marshal_dump(errinfo, io); @@ -3311,11 +3335,11 @@ send_child_error(int fd, int state, char *errmsg, size_t errmsg_buflen, int chfu } } err = errno; - if (write(fd, &err, sizeof(err)) < 0) err = errno; + if (write_retry(fd, &err, sizeof(err)) < 0) err = errno; if (errmsg && 0 < errmsg_buflen) { errmsg[errmsg_buflen-1] = '\0'; errmsg_buflen = strlen(errmsg); - if (errmsg_buflen > 0 && write(fd, errmsg, errmsg_buflen) < 0) + if (errmsg_buflen > 0 && write_retry(fd, errmsg, errmsg_buflen) < 0) err = errno; } if (!NIL_P(io)) rb_io_close(io); @@ -3329,7 +3353,7 @@ recv_child_error(int fd, int *statep, VALUE *excp, int *errp, char *errmsg, size ssize_t size; VALUE exc = Qnil; if (!chfunc_is_async_signal_safe) { - if ((read(fd, &state, sizeof(state))) == sizeof(state) && state) { + if ((read_retry(fd, &state, sizeof(state))) == sizeof(state) && state) { io = rb_io_fdopen(fd, O_RDONLY|O_BINARY, NULL); exc = rb_marshal_load(io); rb_set_errinfo(exc); @@ -3338,7 +3362,7 @@ recv_child_error(int fd, int *statep, VALUE *excp, int *errp, char *errmsg, size *excp = exc; } #define READ_FROM_CHILD(ptr, len) \ - (NIL_P(io) ? read(fd, (ptr), (len)) : rb_io_bufread(io, (ptr), (len))) + (NIL_P(io) ? read_retry(fd, (ptr), (len)) : rb_io_bufread(io, (ptr), (len))) if ((size = READ_FROM_CHILD(&err, sizeof(err))) < 0) { err = errno; } |