From: nobu.nakada@... Date: 2002-08-04T10:12:14+09:00 Subject: [ruby-dev:17911] Re: write EINTR by SIGVTALRM なかだです。 At Sat, 3 Aug 2002 16:57:39 +0900, とみたまさひろ wrote: > まだパッチは試してないですが、ちょっとパッチを眺めてみたんですが、 > write() の EINTR に関しては特に対処されていないようなので、現象は変わ > らないんじゃないかな…と思います。 でした。あの後手元で直したのと間違えてました。 Index: io.c =================================================================== RCS file: /cvs/ruby/src/ruby/io.c,v retrieving revision 1.142 diff -u -2 -p -r1.142 io.c --- io.c 28 Jun 2002 18:26:00 -0000 1.142 +++ io.c 2 Aug 2002 03:34:00 -0000 @@ -259,4 +259,24 @@ io_fflush(f, fptr) } +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 @@ -266,5 +286,6 @@ io_write(io, str) OpenFile *fptr; FILE *f; - long n; + long n, r; + register char *ptr; rb_secure(4); @@ -282,21 +303,34 @@ io_write(io, str) 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)) { + r = fwrite(ptr, 1, n, f); + ptr += r; + n -= r; + if (n || !ferror(f)) break; + switch (errno) { + case EINTR: + 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); @@ -542,4 +576,25 @@ rb_io_to_io(io) /* reading functions */ +static void +io_read_retryable(f, path) + FILE *f; + const char *path; +{ + switch (errno) { + case EINTR: + 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; + } +} static long @@ -583,4 +638,5 @@ io_fread(ptr, len, f) switch (errno) { case EINTR: + clearerr(f); continue; case EAGAIN: @@ -588,4 +644,5 @@ io_fread(ptr, len, f) case EWOULDBLOCK: #endif + clearerr(f); #ifdef __BORLANDC__ case EPIPE: @@ -654,4 +711,5 @@ read_all(fptr, siz) if (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); } @@ -753,6 +811,6 @@ appendline(fptr, delim, strp) if (c == EOF) { if (ferror(f)) { - if (errno == EINTR) continue; - rb_sys_fail(fptr->path); + io_read_retryable(f, fptr->path); + continue; } return c; @@ -1065,6 +1123,6 @@ rb_io_each_byte(io) if (c == EOF) { if (ferror(f)) { - if (errno == EINTR) continue; - rb_sys_fail(fptr->path); + io_read_retryable(f, fptr->path); + continue; } break; @@ -1096,6 +1154,6 @@ 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; -- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦