From: "H.Yamamoto" Date: 2005-08-19T11:33:09+09:00 Subject: [ruby-dev:26830] Re: cannot check EOF of pipe on windows 山本です。 >で、これでめでたしめでたしということでcommitしようかと思った >のですが、bccwin32版にこのパッチを適用すると、mkexports.rbが >Errno::EPIPE例外を発生してしまうようになりました。 >bccのCランタイムのソースを持ってないのでこれ以上追うのは困難 >なのですが、どなたか確認できる方はいらっしゃいませんか? bcc32 では、win32/win32.c の 3209 行あたりですでに #if defined __BORLANDC__ || defined _WIN32_WCE #undef read int read(int fd, void *buf, size_t size) { int trap_immediate = rb_trap_immediate; int ret = _read(fd, buf, size); if ((ret < 0) && (errno == EPIPE)) { errno = 0; ret = 0; } rb_trap_immediate = trap_immediate; catch_interrupt(); return ret; } #endif という形で read の置き換えがされています。これが無効になった ために EPIPE 問題が再発したのではないかと思います。 適当にマージしてみました。 Index: win32.c =================================================================== RCS file: /src/ruby/win32/win32.c,v retrieving revision 1.164 diff -u -w -b -p -r1.164 win32.c --- win32.c 18 Aug 2005 02:07:28 -0000 1.164 +++ win32.c 19 Aug 2005 02:19:18 -0000 @@ -3286,22 +3286,26 @@ catch_interrupt(void) CHECK_INTS; } -#if defined __BORLANDC__ || defined _WIN32_WCE -#undef read -int -read(int fd, void *buf, size_t size) +size_t +rb_w32_read(int fd, void *buf, size_t size) { + int oerr = errno; int trap_immediate = rb_trap_immediate; int ret = _read(fd, buf, size); - if ((ret < 0) && (errno == EPIPE)) { - errno = 0; +#if defined __BORLANDC__ || defined _WIN32_WCE + if (ret < 0 && errno == EPIPE) { + errno = oerr; + ret = 0; + } +#endif + if (ret < 0 && GetLastError() == ERROR_NETNAME_DELETED) { + errno = oerr; ret = 0; } rb_trap_immediate = trap_immediate; catch_interrupt(); return ret; } -#endif #undef fgetc int Index: win32.h =================================================================== RCS file: /src/ruby/win32/win32.h,v retrieving revision 1.70 diff -u -w -b -p -r1.70 win32.h --- win32.h 3 Aug 2005 01:21:20 -0000 1.70 +++ win32.h 19 Aug 2005 02:16:04 -0000 @@ -103,7 +103,6 @@ extern "C++" { #define filelength(h) _filelength(h) #define mktemp(t) _mktemp(t) #define tell(h) _tell(h) -#define unlink(p) _unlink(p) #define write(h, b, l) _write(h, b, l) #define _open _sopen #define sopen _sopen @@ -133,6 +132,8 @@ extern "C++" { #define rmdir(p) rb_w32_rmdir(p) #undef unlink #define unlink(p) rb_w32_unlink(p) +#undef read +#define read(fd, buf, size) rb_w32_read(fd, buf, size) #ifdef __MINGW32__ struct timezone { @@ -200,6 +201,7 @@ extern int rb_w32_isatty(int); extern int rb_w32_mkdir(const char *, int); extern int rb_w32_rmdir(const char *); extern int rb_w32_unlink(const char*); +extern size_t rb_w32_read(int, void *, size_t); #ifdef __BORLANDC__ extern int rb_w32_fstat(int, struct stat *); これで bcc32 win32 ともにエラーにならなくなりました。 でも、何か HEAD と ruby_1_8 で挙動が違いますね・・・ HEAD で stdio を捨てた影響かと思って IO.popen('ruby', 'r+b') としてみましたが同じでした。 E:\ruby-cvs\win32_1_8>ruby -v \z.rb ruby 1.8.3 (2005-08-17) [i386-mswin32] "1" false "\r" false "\n" false "x" false "y" true E:\ruby-cvs\win32>ruby -v \z.rb ruby 1.9.0 (2005-08-18) [i386-mswin32] "1" false "\r" false "\n" true p 1 のかわりに print 1 を使うと E:\ruby-cvs\win32>ruby -v \z.rb ruby 1.9.0 (2005-08-18) [i386-mswin32] "1" false "x" false "y" true となるし、 IO.popen('ruby', 'r+'){|io| io.write %q{ print 1 STDOUT.flush print 'xy' } io.close_write while c = io.read(1) p c p io.eof? end } とすると E:\ruby-cvs\win32>ruby -v \z.rb ruby 1.9.0 (2005-08-18) [i386-mswin32] "1" true 途切れるので、flush が関係してるんでしょうか。