summaryrefslogtreecommitdiff
path: root/process.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-01-25 05:50:44 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-01-25 05:50:44 +0000
commit7336d8c8991d62739fcaa2414c4d2fc6eb754c15 (patch)
tree0fe156510135894d21d3d1e80c0e3b1af84814fa /process.c
parent27dfc398a8cd3b63ccc527c914dee5edd696790e (diff)
process.c: avoid EINTR from Process.spawn
* 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. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@44706 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'process.c')
-rw-r--r--process.c37
1 files changed, 29 insertions, 8 deletions
diff --git a/process.c b/process.c
index 6c29423574..4d484824c5 100644
--- a/process.c
+++ b/process.c
@@ -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);
@@ -3339,11 +3363,8 @@ recv_child_error(int fd, int *statep, VALUE *excp, int *errp, char *errmsg, size
}
#define READ_FROM_CHILD(ptr, len) \
(NIL_P(io) ? read(fd, (ptr), (len)) : rb_io_bufread(io, (ptr), (len)))
- while ((size = READ_FROM_CHILD(&err, sizeof(err))) < 0) {
+ if ((size = READ_FROM_CHILD(&err, sizeof(err))) < 0) {
err = errno;
- if (err != EINTR) {
- break;
- }
}
*errp = err;
if (size == sizeof(err) &&