こんにちは、なかむら(う)です。

In message "[ruby-dev:26915] Re: cannot check EOF of pipe on windows"
    on Aug.30,2005 11:39:10, <usa / garbagecollect.jp> wrote:
| 結局、ソケットでMSVCRTを騙そうという発想は通用しないんかなあ、
| という方向に現状は傾きつつあります。

というわけでパイプ化してみました。
うちでは問題をなぜか再現できないのでこれで直ってるのかどうか
よくわからないのですが、どなたか試してみていただけますか?

気になってるのは、close_write(とclose_read)の処理なのですが、
データが蒸発するようなら教えてくださると嬉しいです。

Index: io.c =================================================================== RCS file: /home/cvs/ruby/io.c,v retrieving revision 1.380 diff -u -1 -p -r1.380 io.c --- io.c 12 Sep 2005 15:23:54 -0000 1.380 +++ io.c 13 Sep 2005 07:02:33 -0000 @@ -2125,2 +2125,3 @@ rb_io_close_read(VALUE io) GetOpenFile(io, fptr); +#ifndef _WIN32 if (is_socket(fptr->fd, fptr->path)) { @@ -2131,2 +2132,3 @@ rb_io_close_read(VALUE io) rb_sys_fail(fptr->path); +#endif fptr->mode &= ~FMODE_READABLE; @@ -2135,3 +2137,5 @@ rb_io_close_read(VALUE io) return Qnil; +#ifndef _WIN32 } + if (fptr->mode & FMODE_WRITABLE) { @@ -2140,2 +2144,3 @@ rb_io_close_read(VALUE io) return rb_io_close(io); +#endif } @@ -2170,2 +2175,3 @@ rb_io_close_write(VALUE io) GetOpenFile(io, fptr); +#ifndef _WIN32 if (is_socket(fptr->fd, fptr->path)) { @@ -2176,2 +2182,3 @@ rb_io_close_write(VALUE io) rb_sys_fail(fptr->path); +#endif fptr->mode &= ~FMODE_WRITABLE; @@ -2180,2 +2187,3 @@ rb_io_close_write(VALUE io) return Qnil; +#ifndef _WIN32 } @@ -2186,2 +2194,3 @@ rb_io_close_write(VALUE io) return rb_io_close(io); +#endif } Index: win32/win32.c =================================================================== RCS file: /home/cvs/ruby/win32/win32.c,v retrieving revision 1.166 diff -u -1 -p -r1.166 win32.c --- win32/win32.c 12 Sep 2005 11:40:40 -0000 1.166 +++ win32/win32.c 13 Sep 2005 07:02:33 -0000 @@ -689,4 +689,48 @@ rb_w32_join_argv(char *cmd, char *const +/* shouldn't call this function on Win9X */ +static BOOL CreatePipeInternal(HANDLE *pr, HANDLE *pw, + LPSECURITY_ATTRIBUTES psa, DWORD size, BOOL bi) +{ + char pname[256]; +#ifdef __MINGW32__ + __attribute__((aligned(4))) +#elif defined(_MSC_VER) /* I hope bcc will align it to correct address... */ + __declspec(align(4)) +#endif + static long id = 0; + DWORD err; + DWORD pmode = bi ? PIPE_ACCESS_DUPLEX : PIPE_ACCESS_INBOUND; + DWORD fmode = bi ? GENERIC_READ | GENERIC_WRITE : GENERIC_WRITE; + + while (1) { + sprintf(pname, "\\\\.\\pipe\\ruby-%lx-%lx", GetCurrentProcessId(), + InterlockedIncrement(&id)); + *pr = CreateNamedPipe(pname, pmode, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, + 1, size, size, NMPWAIT_USE_DEFAULT_WAIT, psa); + if (*pr != INVALID_HANDLE_VALUE) { + break; + } + + err = GetLastError(); + if (err != ERROR_PIPE_BUSY && err != ERROR_ACCESS_DENIED) { + return FALSE; + } + } + + *pw = CreateFile(pname, fmode, 0, psa, OPEN_EXISTING, 0, NULL); + if (*pw == INVALID_HANDLE_VALUE) { + err = GetLastError(); + CloseHandle(*pr); + SetLastError(err); + return FALSE; + } + + return TRUE; +} -static int socketpair_internal(int af, int type, int protocol, SOCKET *sv); +#define CreateBidirectionalPipe(pr, pw, psa, size) \ + CreatePipeInternal(pr, pw, psa, size, TRUE) +#define CreateMonodirectionalPipe(pr, pw, psa, size) \ + (IsWin95() ? CreatePipe(pr, pw, psa, size) : \ + CreatePipeInternal(pr, pw, psa, size, FALSE)) @@ -700,5 +744,3 @@ rb_w32_pipe_exec(const char *cmd, const SECURITY_ATTRIBUTES sa; - BOOL fRet; BOOL reading, writing; - SOCKET pair[2]; int fd; @@ -709,2 +751,6 @@ rb_w32_pipe_exec(const char *cmd, const if (mode & O_RDWR) { + if (IsWin95()) { + errno = EACCES; + return -1; + } reading = writing = TRUE; @@ -733,20 +779,18 @@ rb_w32_pipe_exec(const char *cmd, const if (reading && writing) { - if (socketpair_internal(AF_INET, SOCK_STREAM, 0, pair) < 0) { + if (!CreateBidirectionalPipe(&hIn, &hOut, &sa, 2048L)) { + errno = map_errno(GetLastError()); break; } - if (!DuplicateHandle(hCurProc, (HANDLE)pair[1], hCurProc, - &hDupFile, 0, FALSE, - DUPLICATE_SAME_ACCESS)) { + if (!DuplicateHandle(hCurProc, hOut, hCurProc, &hDupFile, 0, + FALSE, DUPLICATE_SAME_ACCESS)) { errno = map_errno(GetLastError()); - closesocket(pair[0]); - closesocket(pair[1]); - CloseHandle(hCurProc); + CloseHandle(hIn); + CloseHandle(hOut); break; } - closesocket(pair[1]); - hOrg = hIn = hOut = (HANDLE)pair[0]; + CloseHandle(hOut); + hOrg = hOut = hIn; } else if (reading) { - fRet = CreatePipe(&hIn, &hOut, &sa, 2048L); - if (!fRet) { + if (!CreateMonodirectionalPipe(&hIn, &hOut, &sa, 2048L)) { errno = map_errno(GetLastError()); @@ -759,3 +803,2 @@ rb_w32_pipe_exec(const char *cmd, const CloseHandle(hOut); - CloseHandle(hCurProc); break; @@ -767,4 +810,3 @@ rb_w32_pipe_exec(const char *cmd, const else { /* writing */ - fRet = CreatePipe(&hIn, &hOut, &sa, 2048L); - if (!fRet) { + if (!CreateMonodirectionalPipe(&hIn, &hOut, &sa, 2048L)) { errno = map_errno(GetLastError()); @@ -777,3 +819,2 @@ rb_w32_pipe_exec(const char *cmd, const CloseHandle(hOut); - CloseHandle(hCurProc); break; @@ -784,3 +825,2 @@ rb_w32_pipe_exec(const char *cmd, const } - CloseHandle(hCurProc);
余計なところも触ってるように見えるのは将来の布石なので気にし ないでくだちゃい。 それでは。 -- U.Nakamura <usa / garbagecollect.jp>