Skip to content

Commit 75b6ced

Browse files
nobutmm1
authored andcommitted
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://svn.ruby-lang.org/ruby/trunk@44706 b2dd03c8-39d4-4d8f-98ff-823fe69b080e Conflicts: ChangeLog
1 parent 51607af commit 75b6ced

File tree

1 file changed

+29
-8
lines changed

1 file changed

+29
-8
lines changed

process.c

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3296,26 +3296,50 @@ retry_fork(int *status, int *ep, int chfunc_is_async_signal_safe)
32963296
}
32973297
}
32983298

3299+
static ssize_t
3300+
write_retry(int fd, const void *buf, size_t len)
3301+
{
3302+
ssize_t w;
3303+
3304+
do {
3305+
w = write(fd, buf, len);
3306+
} while (w < 0 && errno == EINTR);
3307+
3308+
return w;
3309+
}
3310+
3311+
static ssize_t
3312+
read_retry(int fd, void *buf, size_t len)
3313+
{
3314+
ssize_t r;
3315+
3316+
do {
3317+
r = read(fd, buf, len);
3318+
} while (r < 0 && errno == EINTR);
3319+
3320+
return r;
3321+
}
3322+
32993323
static void
33003324
send_child_error(int fd, int state, char *errmsg, size_t errmsg_buflen, int chfunc_is_async_signal_safe)
33013325
{
33023326
VALUE io = Qnil;
33033327
int err;
33043328

33053329
if (!chfunc_is_async_signal_safe) {
3306-
if (write(fd, &state, sizeof(state)) == sizeof(state) && state) {
3330+
if (write_retry(fd, &state, sizeof(state)) == sizeof(state) && state) {
33073331
VALUE errinfo = rb_errinfo();
33083332
io = rb_io_fdopen(fd, O_WRONLY|O_BINARY, NULL);
33093333
rb_marshal_dump(errinfo, io);
33103334
rb_io_flush(io);
33113335
}
33123336
}
33133337
err = errno;
3314-
if (write(fd, &err, sizeof(err)) < 0) err = errno;
3338+
if (write_retry(fd, &err, sizeof(err)) < 0) err = errno;
33153339
if (errmsg && 0 < errmsg_buflen) {
33163340
errmsg[errmsg_buflen-1] = '\0';
33173341
errmsg_buflen = strlen(errmsg);
3318-
if (errmsg_buflen > 0 && write(fd, errmsg, errmsg_buflen) < 0)
3342+
if (errmsg_buflen > 0 && write_retry(fd, errmsg, errmsg_buflen) < 0)
33193343
err = errno;
33203344
}
33213345
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
33293353
ssize_t size;
33303354
VALUE exc = Qnil;
33313355
if (!chfunc_is_async_signal_safe) {
3332-
if ((read(fd, &state, sizeof(state))) == sizeof(state) && state) {
3356+
if ((read_retry(fd, &state, sizeof(state))) == sizeof(state) && state) {
33333357
io = rb_io_fdopen(fd, O_RDONLY|O_BINARY, NULL);
33343358
exc = rb_marshal_load(io);
33353359
rb_set_errinfo(exc);
@@ -3339,11 +3363,8 @@ recv_child_error(int fd, int *statep, VALUE *excp, int *errp, char *errmsg, size
33393363
}
33403364
#define READ_FROM_CHILD(ptr, len) \
33413365
(NIL_P(io) ? read(fd, (ptr), (len)) : rb_io_bufread(io, (ptr), (len)))
3342-
while ((size = READ_FROM_CHILD(&err, sizeof(err))) < 0) {
3366+
if ((size = READ_FROM_CHILD(&err, sizeof(err))) < 0) {
33433367
err = errno;
3344-
if (err != EINTR) {
3345-
break;
3346-
}
33473368
}
33483369
*errp = err;
33493370
if (size == sizeof(err) &&

0 commit comments

Comments
 (0)