From f150a381db5b51552b714e9a5893654cd056962c Mon Sep 17 00:00:00 2001 From: nobu Date: Sat, 12 Sep 2015 05:23:22 +0000 Subject: win32.c: more fcntl * win32/win32.c (fcntl): implement F_GETFD, F_SETFD, and F_DUPFD_CLOEXEC. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51831 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 5 +++++ include/ruby/win32.h | 5 ++--- test/ruby/test_process.rb | 2 +- win32/win32.c | 47 ++++++++++++++++++++++++++++++++++++++++------- 4 files changed, 48 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index 21f8d0efd5..f32bd51d0a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Sat Sep 12 14:23:20 2015 Nobuyoshi Nakada + + * win32/win32.c (fcntl): implement F_GETFD, F_SETFD, and + F_DUPFD_CLOEXEC. + Sat Sep 12 05:35:24 2015 Eric Wong * rational.c (string_to_r_strict): preserve encoding in exception diff --git a/include/ruby/win32.h b/include/ruby/win32.h index 0d07745eda..c26aa9d4f9 100644 --- a/include/ruby/win32.h +++ b/include/ruby/win32.h @@ -577,15 +577,14 @@ extern char *rb_w32_strerror(int); #endif #define F_DUPFD 0 -#if 0 #define F_GETFD 1 #define F_SETFD 2 +#if 0 #define F_GETFL 3 #endif #define F_SETFL 4 -#if 0 +#define F_DUPFD_CLOEXEC 67 #define FD_CLOEXEC 1 /* F_GETFD, F_SETFD */ -#endif #define O_NONBLOCK 1 #undef FD_SET diff --git a/test/ruby/test_process.rb b/test/ruby/test_process.rb index e26d0a46a5..32dcaed144 100644 --- a/test/ruby/test_process.rb +++ b/test/ruby/test_process.rb @@ -970,7 +970,7 @@ class TestProcess < Test::Unit::TestCase rescue NotImplementedError skip "IO#close_on_exec= is not supported" end - end + end unless windows? # passing non-stdio fds is not supported on Windows def test_execopts_redirect_tempfile bug6269 = '[ruby-core:44181]' diff --git a/win32/win32.c b/win32/win32.c index d1cfb6bcf5..11292a16cc 100644 --- a/win32/win32.c +++ b/win32/win32.c @@ -4144,8 +4144,10 @@ fcntl(int fd, int cmd, ...) { va_list va; int arg; + DWORD flag; - if (cmd == F_SETFL) { + switch (cmd) { + case F_SETFL: { SOCKET sock = TO_SOCKET(fd); if (!is_socket(sock)) { errno = EBADF; @@ -4156,13 +4158,14 @@ fcntl(int fd, int cmd, ...) arg = va_arg(va, int); va_end(va); return setfl(sock, arg); - } - else if (cmd == F_DUPFD) { + } + case F_DUPFD: case F_DUPFD_CLOEXEC: { int ret; HANDLE hDup; + flag = _osfile(fd); if (!(DuplicateHandle(GetCurrentProcess(), (HANDLE)_get_osfhandle(fd), GetCurrentProcess(), &hDup, 0L, - !(_osfile(fd) & FNOINHERIT), + cmd == F_DUPFD && !(flag & FNOINHERIT), DUPLICATE_SAME_ACCESS))) { errno = map_errno(GetLastError()); return -1; @@ -4172,11 +4175,41 @@ fcntl(int fd, int cmd, ...) arg = va_arg(va, int); va_end(va); - if ((ret = dupfd(hDup, _osfile(fd), arg)) == -1) + if (cmd != F_DUPFD) + flag |= FNOINHERIT; + else + flag &= ~FNOINHERIT; + if ((ret = dupfd(hDup, flag, arg)) == -1) CloseHandle(hDup); return ret; - } - else { + } + case F_GETFD: { + SIGNED_VALUE h = _get_osfhandle(fd); + if (h == -1) return -1; + if (!GetHandleInformation((HANDLE)h, &flag)) { + errno = map_errno(GetLastError()); + return -1; + } + return (flag & HANDLE_FLAG_INHERIT) ? 0 : FD_CLOEXEC; + } + case F_SETFD: { + SIGNED_VALUE h = _get_osfhandle(fd); + if (h == -1) return -1; + va_start(va, cmd); + arg = va_arg(va, int); + va_end(va); + if (!SetHandleInformation((HANDLE)h, HANDLE_FLAG_INHERIT, + (arg & FD_CLOEXEC) ? 0 : HANDLE_FLAG_INHERIT)) { + errno = map_errno(GetLastError()); + return -1; + } + if (arg & FD_CLOEXEC) + _osfile(fd) |= FNOINHERIT; + else + _osfile(fd) &= ~FNOINHERIT; + return 0; + } + default: errno = EINVAL; return -1; } -- cgit v1.2.3