diff --git a/ChangeLog b/ChangeLog index a07ccdf508..a2d6d18f6c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +Tue Nov 20 13:00:44 2007 NAKAMURA Usaku + + * include/ruby/win32.h win32/win32.c (rb_w32_pipe_exec): use dual fd + instead of socketpair when mode is RDWR. + + * io.c (pipe_open): pass &write_fd to rb_w32_pipe_exec(). + + * io.c (popen_redirect): define only when HAVE_FORK. + Tue Nov 20 12:12:04 2007 Tanaka Akira * include/ruby/io.h (rb_io_t): add tied_io_for_writing member. diff --git a/include/ruby/win32.h b/include/ruby/win32.h index 02021f19d9..79e3396892 100644 --- a/include/ruby/win32.h +++ b/include/ruby/win32.h @@ -206,7 +206,7 @@ struct timezone { #endif #define NtInitialize ruby_sysinit extern int rb_w32_cmdvector(const char *, char ***); -extern rb_pid_t rb_w32_pipe_exec(const char *, const char *, int, int *); +extern rb_pid_t rb_w32_pipe_exec(const char *, const char *, int, int *, int *); extern int flock(int fd, int oper); extern int rb_w32_is_socket(int); extern int WSAAPI rb_w32_accept(int, struct sockaddr *, int *); diff --git a/io.c b/io.c index 4ba19005be..369f0b0e59 100644 --- a/io.c +++ b/io.c @@ -3138,6 +3138,7 @@ rb_io_unbuffered(rb_io_t *fptr) rb_io_synchronized(fptr); } +#ifdef HAVE_FORK struct popen_arg { struct rb_exec_arg exec; int modef; @@ -3176,7 +3177,6 @@ popen_redirect(struct popen_arg *p) } } -#ifdef HAVE_FORK static int popen_exec(void *pp) { @@ -3299,7 +3299,7 @@ pipe_open(const char *cmd, int argc, VALUE *argv, const char *mode) exename = cmd; cmd = rb_w32_join_argv(ALLOCA_N(char, rb_w32_argv_size(args)), args); } - while ((pid = rb_w32_pipe_exec(cmd, exename, openmode, &fd)) == -1) { + while ((pid = rb_w32_pipe_exec(cmd, exename, openmode, &fd, &write_fd)) == -1) { /* exec failed */ switch (errno) { case EAGAIN: diff --git a/version.h b/version.h index d02a2eaa5d..fd2f91e7f5 100644 --- a/version.h +++ b/version.h @@ -1,7 +1,7 @@ #define RUBY_VERSION "1.9.0" -#define RUBY_RELEASE_DATE "2007-11-19" +#define RUBY_RELEASE_DATE "2007-11-20" #define RUBY_VERSION_CODE 190 -#define RUBY_RELEASE_CODE 20071119 +#define RUBY_RELEASE_CODE 20071120 #define RUBY_PATCHLEVEL 0 #define RUBY_VERSION_MAJOR 1 @@ -9,7 +9,7 @@ #define RUBY_VERSION_TEENY 0 #define RUBY_RELEASE_YEAR 2007 #define RUBY_RELEASE_MONTH 11 -#define RUBY_RELEASE_DAY 19 +#define RUBY_RELEASE_DAY 20 #ifdef RUBY_EXTERN RUBY_EXTERN const char ruby_version[]; diff --git a/win32/win32.c b/win32/win32.c index 99199c95af..d9178da13b 100644 --- a/win32/win32.c +++ b/win32/win32.c @@ -706,39 +706,32 @@ rb_w32_join_argv(char *cmd, char *const *argv) static int socketpair_internal(int af, int type, int protocol, SOCKET *sv); rb_pid_t -rb_w32_pipe_exec(const char *cmd, const char *prog, int mode, int *pipe) +rb_w32_pipe_exec(const char *cmd, const char *prog, int mode, int *pipe, int *write_pipe) { struct ChildRecord* child; - HANDLE hOrg, hIn, hOut; - HANDLE hDupFile; + HANDLE hIn, hOut; + HANDLE hDupIn, hDupOut; HANDLE hCurProc; SECURITY_ATTRIBUTES sa; BOOL reading, writing; SOCKET pair[2]; int fd; - int pipemode; + int binmode; int ret; /* Figure out what we're doing... */ if (mode & O_RDWR) { - if (IsWin95()) { - errno = EINVAL; - return -1; - } reading = writing = TRUE; - pipemode = _O_RDWR; } else if (mode & O_WRONLY) { reading = FALSE; writing = TRUE; - pipemode = _O_WRONLY; } else { reading = TRUE; writing = FALSE; - pipemode = _O_RDONLY; } - pipemode |= (mode & O_BINARY) ? O_BINARY : O_TEXT; + binmode |= (mode & O_BINARY) ? O_BINARY : O_TEXT; sa.nLength = sizeof (SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; @@ -748,68 +741,72 @@ rb_w32_pipe_exec(const char *cmd, const char *prog, int mode, int *pipe) RUBY_CRITICAL(do { /* create pipe */ hCurProc = GetCurrentProcess(); - if (reading && writing) { - if (socketpair_internal(AF_INET, SOCK_STREAM, 0, pair) < 0) { - break; - } - if (!DuplicateHandle(hCurProc, (HANDLE)pair[1], hCurProc, - &hDupFile, 0, FALSE, - DUPLICATE_SAME_ACCESS)) { - errno = map_errno(GetLastError()); - closesocket(pair[0]); - closesocket(pair[1]); - CloseHandle(hCurProc); - break; - } - closesocket(pair[1]); - hOrg = hIn = hOut = (HANDLE)pair[0]; - } - else if (reading) { - if (!CreatePipe(&hIn, &hOut, &sa, 2048L)) { + hIn = hOut = hDupIn = hDupOut = NULL; + if (reading) { + HANDLE hTmpIn; + if (!CreatePipe(&hTmpIn, &hOut, &sa, 2048L)) { errno = map_errno(GetLastError()); break; } - if (!DuplicateHandle(hCurProc, hIn, hCurProc, &hDupFile, 0, + if (!DuplicateHandle(hCurProc, hTmpIn, hCurProc, &hDupIn, 0, FALSE, DUPLICATE_SAME_ACCESS)) { errno = map_errno(GetLastError()); - CloseHandle(hIn); + CloseHandle(hTmpIn); CloseHandle(hOut); break; } - CloseHandle(hIn); - hIn = NULL; - hOrg = hOut; + CloseHandle(hTmpIn); + hTmpIn = NULL; } - else { /* writing */ - if (!CreatePipe(&hIn, &hOut, &sa, 2048L)) { + if (writing) { + HANDLE hTmpOut; + if (!CreatePipe(&hIn, &hTmpOut, &sa, 2048L)) { errno = map_errno(GetLastError()); break; } - if (!DuplicateHandle(hCurProc, hOut, hCurProc, &hDupFile, 0, + if (!DuplicateHandle(hCurProc, hTmpOut, hCurProc, &hDupOut, 0, FALSE, DUPLICATE_SAME_ACCESS)) { errno = map_errno(GetLastError()); CloseHandle(hIn); - CloseHandle(hOut); + CloseHandle(hTmpOut); break; } - CloseHandle(hOut); - hOut = NULL; - hOrg = hIn; + CloseHandle(hTmpOut); + hTmpOut = NULL; } /* create child process */ child = CreateChild(cmd, prog, &sa, hIn, hOut, NULL); if (!child) { - CloseHandle(hOrg); - CloseHandle(hDupFile); + if (hIn) + CloseHandle(hIn); + if (hOut) + CloseHandle(hOut); + if (hDupIn) + CloseHandle(hDupIn); + if (hDupOut) + CloseHandle(hDupOut); break; } /* associate handle to file descritor */ - *pipe = rb_w32_open_osfhandle((intptr_t)hDupFile, pipemode); - CloseHandle(hOrg); + if (reading) { + *pipe = rb_w32_open_osfhandle((intptr_t)hDupIn, _O_RDONLY | binmode); + if (writing) + *write_pipe = rb_w32_open_osfhandle((intptr_t)hDupOut, _O_WRONLY | binmode); + } + else { + *pipe = rb_w32_open_osfhandle((intptr_t)hDupOut, _O_WRONLY | binmode); + } + if (hIn) + CloseHandle(hIn); + if (hOut) + CloseHandle(hOut); if (*pipe == -1) { - CloseHandle(hDupFile); + if (hDupIn) + CloseHandle(hDupIn); + if (hDupOut) + CloseHandle(hDupOut); CloseChildHandle(child); break; }