山本です。 >//---------------------------------------------------------------- >// Thread: [ruby-dev:23730] >// Subject: test/ruby/test_pipe.rb で EOF のテストに失敗する問題 (bcc32) >// Reason: Win32APIのReadFile は、書き込み端が閉じている名前なしパイプに >// 対してデータ以上読もうとすると、GetLastError に ERROR_BROKEN_PIPE >// を設定して失敗する。bcc32のfreadはこれに対処していないため、 >// EOFフラグが立たずEPIPE例外になる。 >//---------------------------------------------------------------- fread() だけでなく、read() のほうも対処が必要でした。 あと、返り値とerrnoを正常化してなかったので、修正しました。 あと、「データ以上読もうとすると」というのは厳密には正しくなくて、 ・4バイト書き込む ・5バイト読み込む(データ以上だが、まだ ERROR_PIPE_BROKEN にはならない。 4バイト読み込んで成功する) ・任意のバイト数(0を含む)を読み込む(ERROR_PIPE_BROKENで失敗する) です。 Index: win32.c =================================================================== RCS file: /var/cvs/src/ruby/win32/win32.c,v retrieving revision 1.117 diff -u -w -b -p -r1.117 win32.c --- win32.c 21 Jun 2004 00:27:39 -0000 1.117 +++ win32.c 6 Jul 2004 02:08:21 -0000 @@ -3034,10 +3034,16 @@ rb_w32_getc(FILE* stream) else #endif { +#if defined __BORLANDC__ || defined _WIN32_WCE + errno = 0; +#endif c = _filbuf(stream); #if defined __BORLANDC__ || defined _WIN32_WCE - if ((c == EOF) && (errno == EPIPE)) { + if (errno == EPIPE) { + errno = 0; + c = EOF; clearerr(stream); + stream->flags |= _F_EOF; } #endif rb_trap_immediate = trap_immediate; @@ -3065,6 +3071,42 @@ rb_w32_putc(int c, FILE* stream) } return c; } + +#if defined __BORLANDC__ || defined _WIN32_WCE +#undef read +int rb_w32_read(int handle, void *buf, unsigned len) +{ + int ret; + + errno = 0; +#if defined __BORLANDC__ + ret = _read(handle, buf, len); +#else + ret = read(handle, buf, len); +#endif + if (errno == EPIPE) { + errno = 0; + ret = 0; + } + return ret; +} + +#undef fread +size_t rb_w32_fread(void *ptr, size_t size, size_t n, FILE *stream) +{ + size_t ret; + + errno = 0; + ret = fread(ptr, size, n, stream); + if (errno == EPIPE) { + errno = 0; + ret = 0; + clearerr(stream); + stream->flags |= _F_EOF; + } + return ret; +} +#endif struct asynchronous_arg_t { /* output field */ Index: win32.h =================================================================== RCS file: /var/cvs/src/ruby/win32/win32.h,v retrieving revision 1.51 diff -u -w -b -p -r1.51 win32.h --- win32.h 19 Feb 2004 09:08:23 -0000 1.51 +++ win32.h 6 Jul 2004 02:42:30 -0000 @@ -106,7 +106,6 @@ extern "C++" { #define filelength(h) _filelength(h) #define mktemp(t) _mktemp(t) #define perror(s) _perror(s) -#define read(h, b, l) _read(h, b, l) #define tell(h) _tell(h) #define umask(m) _umask(m) #define unlink(p) _unlink(p) @@ -121,6 +120,12 @@ extern "C++" { #define stat(path,st) rb_w32_stat(path,st) #undef execv #define execv(path,argv) rb_w32_aspawn(P_OVERLAY,path,argv) +#if defined __BORLANDC__ || defined _WIN32_WCE +#undef read +#define read(p, s, l) rb_w32_read(p, s, l) +#undef fread +#define fread(p, s, n, stream) rb_w32_fread(p, s, n, stream) +#endif #ifdef __MINGW32__ struct timezone { @@ -179,6 +184,15 @@ extern int rb_w32_aspawn(int, const char extern int kill(int, int); extern pid_t rb_w32_getpid(void); +extern int rb_w32_stat(const char *, struct stat *); +#if defined __BORLANDC__ +extern int rb_w32_fstat(int, struct stat *); +#endif +#if defined __BORLANDC__ || defined _WIN32_WCE +extern int rb_w32_read(int handle, void *buf, unsigned len); +extern size_t rb_w32_fread(void *, size_t, size_t, FILE *); +#endif + #include <float.h> #if !defined __MINGW32__ || defined __NO_ISOCEXT #ifndef isnan @@ -189,7 +203,7 @@ extern pid_t rb_w32_getpid(void); #endif #endif -#if 0 && defined __BORLANDC__ +#if defined __BORLANDC__ #undef S_ISDIR #undef S_ISFIFO #undef S_ISBLK