こんにちは、なかむら(う)です。
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>