山本です。bcc32 の fopen, fdopen, fsopen が正しく errno を設定しない 件ですが、やっぱりパッチを当ててもいいでしょうか?落ちるのはあんまりな気がしてきました。 >> [ruby-dev:23743] ///////////////////////////////// // パッチを当てる前 E:\ruby-cvs\ruby>..\miniruby.exe -e "IO.for_fd(-1)" -e:1:in `for_fd': Invalid argument (Errno::EINVAL) from -e:1 E:\ruby-cvs\ruby>..\miniruby.exe -e "p 100.times { open('makefile') }" -e:1: [BUG] rb_sys_fail(makefile) - errno == 0 ruby 1.9.0 (2004-07-23) [i386-bccwin32] Abnormal program termination E:\ruby-cvs\ruby>..\miniruby.exe -e "Array.new(100) { open('makefile') }" -e:1: [BUG] rb_sys_fail(makefile) - errno == 0 ruby 1.9.0 (2004-07-23) [i386-bccwin32] Abnormal program termination ///////////////////////////////// // パッチを当てた後 E:\ruby-cvs\ruby>miniruby.exe -e "IO.for_fd(-1)" -e:1:in `for_fd': Bad file number (Errno::EBADF) from -e:1 E:\ruby-cvs\ruby>miniruby.exe -e "p 100.times { open('makefile') }" 100 # EMFILE のとき GC を行うので、問題なく終了している E:\ruby-cvs\ruby>miniruby.exe -e "Array.new(100) { open('makefile') }" -e:1:in `initialize': Too many open files (Errno::EMFILE) - makefile from -e:1:in `open' from -e:1 from -e:1:in `initialize' from -e:1:in `new' from -e:1 ////////////////////////////////// // パッチ 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 24 Jul 2004 09:08:34 -0000 @@ -3330,3 +3330,51 @@ rb_w32_snprintf(char *buf, size_t size, va_end(va); return ret; } + +#ifdef __BORLANDC__ +static int +too_many_files() +{ + FILE *f; + for (f = _streams; f < _streams + _nfile; f++) { + if (f->fd < 0) return 0; + } + return 1; +} + +#undef fopen +FILE * +rb_w32_fopen(const char *path, const char *mode) +{ + FILE *f = (errno = 0, fopen(path, mode)); + if (f == NULL && errno == 0) { + if (too_many_files()) + errno = EMFILE; + } + return f; +} + +FILE * +rb_w32_fdopen(int handle, char *type) +{ + FILE *f = (errno = 0, _fdopen(handle, type)); + if (f == NULL && errno == 0) { + if (handle < 0) + errno = EBADF; + else if (too_many_files()) + errno = EMFILE; + } + return f; +} + +FILE * +rb_w32_fsopen(const char *path, const char *mode, int shflags) +{ + FILE *f = (errno = 0, _fsopen(path, mode, shflags)); + if (f == NULL && errno == 0) { + if (too_many_files()) + errno = EMFILE; + } + return f; +} +#endif 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 24 Jul 2004 08:57:25 -0000 @@ -115,6 +115,12 @@ extern "C++" { #define sopen _sopen #undef fstat #define fstat(fd,st) rb_w32_fstat(fd,st) +#undef fopen +#define fopen(p, m) rb_w32_fopen(p, m) +#undef fdopen +#define fdopen(h, m) rb_w32_fdopen(h, m) +#undef fsopen +#define fsopen(p, m, sh) rb_w32_fsopen(p, m, sh) #endif #define fsync(h) _commit(h) #undef stat @@ -178,6 +184,13 @@ extern int rb_w32_spawn(int, const char extern int rb_w32_aspawn(int, const char *, char *const *); extern int kill(int, int); extern pid_t rb_w32_getpid(void); + +#ifdef __BORLANDC__ +extern int rb_w32_fstat(int, struct stat *); +extern FILE *rb_w32_fopen(const char *, const char *); +extern FILE *rb_w32_fdopen(int, char *); +extern FILE *rb_w32_fsopen(const char *, const char *, int); +#endif #include <float.h> #if !defined __MINGW32__ || defined __NO_ISOCEXT