summaryrefslogtreecommitdiff
path: root/io.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2002-09-11 01:09:04 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2002-09-11 01:09:04 +0000
commitf34534c52afc423e3b48b54c1b127c26098b59de (patch)
tree26af4cb5b8e7dbd9d11ccbf28187c2d14556d514 /io.c
parenta82da9463f1a878c9f92c117e645b77425ab2b08 (diff)
retry on EINTR, ERESTART and EWOULDBLOCK. [ruby-dev:17855], [ruby-dev:17878], [ruby-core:00444]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2841 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'io.c')
-rw-r--r--io.c107
1 files changed, 86 insertions, 21 deletions
diff --git a/io.c b/io.c
index 90338e6f2a..e6c873604d 100644
--- a/io.c
+++ b/io.c
@@ -261,6 +261,26 @@ io_fflush(f, fptr)
fptr->mode &= ~FMODE_WBUF;
}
+void
+rb_io_wait_readable(f)
+ int f;
+{
+ fd_set rfds;
+ FD_ZERO(&rfds);
+ FD_SET(f, &rfds);
+ rb_thread_select(f + 1, &rfds, NULL, NULL, NULL);
+}
+
+void
+rb_io_wait_writable(f)
+ int f;
+{
+ fd_set wfds;
+ FD_ZERO(&wfds);
+ FD_SET(f, &wfds);
+ rb_thread_select(f + 1, NULL, &wfds, NULL, NULL);
+}
+
/* writing functions */
static VALUE
io_write(io, str)
@@ -268,7 +288,8 @@ io_write(io, str)
{
OpenFile *fptr;
FILE *f;
- long n;
+ long n, r;
+ register char *ptr;
rb_secure(4);
if (TYPE(str) != T_STRING)
@@ -284,23 +305,40 @@ io_write(io, str)
rb_io_check_writable(fptr);
f = GetWriteFile(fptr);
+ ptr = RSTRING(str)->ptr;
+ n = RSTRING(str)->len;
+ do {
#ifdef __human68k__
- {
- register char *ptr = RSTRING(str)->ptr;
- n = RSTRING(str)->len;
- while (--n >= 0)
- if (fputc(*ptr++, f) == EOF)
- break;
- n = ptr - RSTRING(str)->ptr;
- }
- if (n != RSTRING(str)->len && ferror(f))
- rb_sys_fail(fptr->path);
+ if (fputc(*ptr++, f) == EOF) {
+ if (ferror(f)) rb_sys_fail(fptr->path);
+ break;
+ }
+ --n;
#else
- n = fwrite(RSTRING(str)->ptr, 1, RSTRING(str)->len, f);
- if (n != RSTRING(str)->len && ferror(f)) {
- rb_sys_fail(fptr->path);
- }
+ r = fwrite(ptr, 1, n, f);
+ ptr += r;
+ n -= r;
+ if (ferror(f)) {
+ switch (errno) {
+ case EINTR:
+#if defined(ERESTART)
+ case ERESTART:
#endif
+ clearerr(f);
+ continue;
+ case EAGAIN:
+#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
+ case EWOULDBLOCK:
+#endif
+ clearerr(f);
+ rb_io_wait_writable(fileno(f));
+ continue;
+ }
+ rb_sys_fail(fptr->path);
+ }
+#endif
+ } while (n > 0);
+ n = ptr - RSTRING(str)->ptr;
if (fptr->mode & FMODE_SYNC) {
io_fflush(f, fptr);
}
@@ -544,6 +582,30 @@ rb_io_to_io(io)
}
/* reading functions */
+static void
+io_read_retryable(f, path)
+ FILE *f;
+ const char *path;
+{
+ switch (errno) {
+ case EINTR:
+#if defined(ERESTART)
+ case ERESTART:
+#endif
+ clearerr(f);
+ break;
+ case EAGAIN:
+#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
+ case EWOULDBLOCK:
+#endif
+ clearerr(f);
+ rb_io_wait_readable(fileno(f));
+ break;
+ default:
+ rb_sys_fail(path);
+ break;
+ }
+}
long
rb_io_fread(ptr, len, f)
@@ -585,11 +647,13 @@ rb_io_fread(ptr, len, f)
if (ferror(f)) {
switch (errno) {
case EINTR:
+ clearerr(f);
continue;
case EAGAIN:
#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
case EWOULDBLOCK:
#endif
+ clearerr(f);
return len - n;
}
return 0;
@@ -654,6 +718,7 @@ read_all(fptr, siz)
n = rb_io_fread(RSTRING(str)->ptr+bytes, siz-bytes, fptr->f);
if (pos > 0 && n == 0 && bytes == 0) {
if (feof(fptr->f)) return Qnil;
+ if (!ferror(fptr->f)) return rb_str_new(0, 0);
rb_sys_fail(fptr->path);
}
bytes += n;
@@ -765,8 +830,8 @@ appendline(fptr, delim, strp)
TRAP_END;
if (c == EOF) {
if (ferror(f)) {
- if (errno == EINTR) continue;
- rb_sys_fail(fptr->path);
+ io_read_retryable(f, fptr->path);
+ continue;
}
return c;
}
@@ -1078,8 +1143,8 @@ rb_io_each_byte(io)
TRAP_END;
if (c == EOF) {
if (ferror(f)) {
- if (errno == EINTR) continue;
- rb_sys_fail(fptr->path);
+ io_read_retryable(f, fptr->path);
+ continue;
}
break;
}
@@ -1109,8 +1174,8 @@ rb_io_getc(io)
if (c == EOF) {
if (ferror(f)) {
- if (errno == EINTR) goto retry;
- rb_sys_fail(fptr->path);
+ io_read_retryable(f, fptr->path);
+ goto retry;
}
return Qnil;
}