[pypy-commit] pypy default: Win32: fix set_inheritable tests
arigo
pypy.commits at gmail.com
Tue Nov 8 12:45:46 EST 2016
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r88223:405237fca758
Date: 2016-11-08 18:44 +0100
http://bitbucket.org/pypy/pypy/changeset/405237fca758/
Log: Win32: fix set_inheritable tests
diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py
--- a/rpython/rlib/rposix.py
+++ b/rpython/rlib/rposix.py
@@ -1166,6 +1166,10 @@
@replace_os_function('pipe')
def pipe(flags=0):
# 'flags' might be ignored. Check the result.
+ # The handles returned are always inheritable on Posix.
+ # The situation on Windows is not completely clear: I think
+ # it should always return non-inheritable handles, but CPython
+ # uses SECURITY_ATTRIBUTES to ensure that and we don't.
if _WIN32:
# 'flags' ignored
ralloc = lltype.scoped_alloc(rwin32.LPHANDLE.TO, 1)
@@ -2146,8 +2150,9 @@
handle_posix_error('mknodat', error)
-eci_inheritable = eci.merge(ExternalCompilationInfo(
- separate_module_sources=[r"""
+if not _WIN32:
+ eci_inheritable = eci.merge(ExternalCompilationInfo(
+ separate_module_sources=[r"""
#include <errno.h>
#include <sys/ioctl.h>
@@ -2200,10 +2205,6 @@
RPY_EXTERN
int rpy_dup_noninheritable(int fd)
{
-#ifdef _WIN32
-#error NotImplementedError
-#endif
-
#ifdef F_DUPFD_CLOEXEC
return fcntl(fd, F_DUPFD_CLOEXEC, 0);
#else
@@ -2221,10 +2222,6 @@
RPY_EXTERN
int rpy_dup2_noninheritable(int fd, int fd2)
{
-#ifdef _WIN32
-#error NotImplementedError
-#endif
-
#ifdef F_DUP2FD_CLOEXEC
return fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
@@ -2249,33 +2246,41 @@
return 0;
#endif
}
- """ % {'HAVE_DUP3': HAVE_DUP3}],
- post_include_bits=['RPY_EXTERN int rpy_set_inheritable(int, int);\n'
- 'RPY_EXTERN int rpy_get_inheritable(int);\n'
- 'RPY_EXTERN int rpy_dup_noninheritable(int);\n'
- 'RPY_EXTERN int rpy_dup2_noninheritable(int, int);\n']))
+ """ % {'HAVE_DUP3': HAVE_DUP3}],
+ post_include_bits=['RPY_EXTERN int rpy_set_inheritable(int, int);\n'
+ 'RPY_EXTERN int rpy_get_inheritable(int);\n'
+ 'RPY_EXTERN int rpy_dup_noninheritable(int);\n'
+ 'RPY_EXTERN int rpy_dup2_noninheritable(int, int);\n'
+ ]))
-c_set_inheritable = external('rpy_set_inheritable', [rffi.INT, rffi.INT],
- rffi.INT, save_err=rffi.RFFI_SAVE_ERRNO,
- compilation_info=eci_inheritable)
-c_get_inheritable = external('rpy_get_inheritable', [rffi.INT],
- rffi.INT, save_err=rffi.RFFI_SAVE_ERRNO,
- compilation_info=eci_inheritable)
-c_dup_noninheritable = external('rpy_dup_noninheritable', [rffi.INT],
- rffi.INT, save_err=rffi.RFFI_SAVE_ERRNO,
- compilation_info=eci_inheritable)
-c_dup2_noninheritable = external('rpy_dup2_noninheritable', [rffi.INT,rffi.INT],
- rffi.INT, save_err=rffi.RFFI_SAVE_ERRNO,
- compilation_info=eci_inheritable)
+ _c_set_inheritable = external('rpy_set_inheritable', [rffi.INT, rffi.INT],
+ rffi.INT, save_err=rffi.RFFI_SAVE_ERRNO,
+ compilation_info=eci_inheritable)
+ _c_get_inheritable = external('rpy_get_inheritable', [rffi.INT],
+ rffi.INT, save_err=rffi.RFFI_SAVE_ERRNO,
+ compilation_info=eci_inheritable)
+ c_dup_noninheritable = external('rpy_dup_noninheritable', [rffi.INT],
+ rffi.INT, save_err=rffi.RFFI_SAVE_ERRNO,
+ compilation_info=eci_inheritable)
+ c_dup2_noninheritable = external('rpy_dup2_noninheritable', [rffi.INT,rffi.INT],
+ rffi.INT, save_err=rffi.RFFI_SAVE_ERRNO,
+ compilation_info=eci_inheritable)
-def set_inheritable(fd, inheritable):
- result = c_set_inheritable(fd, inheritable)
- handle_posix_error('set_inheritable', result)
+ def set_inheritable(fd, inheritable):
+ result = _c_set_inheritable(fd, inheritable)
+ handle_posix_error('set_inheritable', result)
-def get_inheritable(fd):
- res = c_get_inheritable(fd)
- res = handle_posix_error('get_inheritable', res)
- return res != 0
+ def get_inheritable(fd):
+ res = _c_get_inheritable(fd)
+ res = handle_posix_error('get_inheritable', res)
+ return res != 0
+
+else:
+ # _WIN32
+ from rpython.rlib.rwin32 import set_inheritable, get_inheritable
+ from rpython.rlib.rwin32 import c_dup_noninheritable
+ from rpython.rlib.rwin32 import c_dup2_noninheritable
+
class SetNonInheritableCache(object):
"""Make one prebuilt instance of this for each path that creates
diff --git a/rpython/rlib/rwin32.py b/rpython/rlib/rwin32.py
--- a/rpython/rlib/rwin32.py
+++ b/rpython/rlib/rwin32.py
@@ -112,7 +112,7 @@
CTRL_C_EVENT CTRL_BREAK_EVENT
MB_ERR_INVALID_CHARS ERROR_NO_UNICODE_TRANSLATION
WC_NO_BEST_FIT_CHARS STD_INPUT_HANDLE STD_OUTPUT_HANDLE
- STD_ERROR_HANDLE
+ STD_ERROR_HANDLE HANDLE_FLAG_INHERIT FILE_TYPE_CHAR
"""
from rpython.translator.platform import host_factory
static_platform = host_factory()
@@ -473,3 +473,56 @@
CONSOLE_SCREEN_BUFFER_INFO_P = lltype.Ptr(CONSOLE_SCREEN_BUFFER_INFO)
GetConsoleScreenBufferInfo = winexternal(
"GetConsoleScreenBufferInfo", [HANDLE, CONSOLE_SCREEN_BUFFER_INFO_P], BOOL)
+
+ _GetHandleInformation = winexternal(
+ 'GetHandleInformation', [HANDLE, LPDWORD], BOOL)
+ _SetHandleInformation = winexternal(
+ 'SetHandleInformation', [HANDLE, DWORD, DWORD], BOOL)
+
+ def set_inheritable(fd, inheritable):
+ handle = get_osfhandle(fd)
+ if inheritable:
+ flags = HANDLE_FLAG_INHERIT
+ else:
+ flags = 0
+ if not _SetHandleInformation(handle, HANDLE_FLAG_INHERIT, flags):
+ raise lastSavedWindowsError("SetHandleInformation")
+
+ def get_inheritable(fd):
+ handle = get_osfhandle(fd)
+ pflags = lltype.malloc(LPDWORD.TO, 1, flavor='raw')
+ try:
+ if not _GetHandleInformation(handle, pflags):
+ raise lastSavedWindowsError("GetHandleInformation")
+ flags = pflags[0]
+ finally:
+ lltype.free(pflags, flavor='raw')
+ return (flags & HANDLE_FLAG_INHERIT) != 0
+
+ _GetFileType = winexternal('GetFileType', [HANDLE], DWORD)
+
+ def c_dup_noninheritable(fd1):
+ from rpython.rlib.rposix import c_dup
+
+ ftype = _GetFileType(get_osfhandle(fd1))
+ fd2 = c_dup(fd1) # the inheritable version
+ if fd2 >= 0 and ftype != FILE_TYPE_CHAR:
+ try:
+ set_inheritable(fd2, False)
+ except:
+ os.close(fd2)
+ raise
+ return fd2
+
+ def c_dup2_noninheritable(fd1, fd2):
+ from rpython.rlib.rposix import c_dup2
+
+ ftype = _GetFileType(get_osfhandle(fd1))
+ res = c_dup2(fd1, fd2) # the inheritable version
+ if res >= 0 and ftype != FILE_TYPE_CHAR:
+ try:
+ set_inheritable(fd2, False)
+ except:
+ os.close(fd2)
+ raise
+ return res
diff --git a/rpython/rlib/test/test_rposix.py b/rpython/rlib/test/test_rposix.py
--- a/rpython/rlib/test/test_rposix.py
+++ b/rpython/rlib/test/test_rposix.py
@@ -604,6 +604,9 @@
def test_SetNonInheritableCache():
cache = rposix.SetNonInheritableCache()
fd1, fd2 = os.pipe()
+ if sys.platform == 'win32':
+ rposix.set_inheritable(fd1, True)
+ rposix.set_inheritable(fd2, True)
assert rposix.get_inheritable(fd1) == True
assert rposix.get_inheritable(fd1) == True
assert cache.cached_inheritable == -1
@@ -616,6 +619,24 @@
os.close(fd1)
os.close(fd2)
+def test_dup_dup2_non_inheritable():
+ for preset in [False, True]:
+ fd1, fd2 = os.pipe()
+ rposix.set_inheritable(fd1, preset)
+ rposix.set_inheritable(fd2, preset)
+ fd3 = rposix.dup(fd1, True)
+ assert rposix.get_inheritable(fd3) == True
+ fd4 = rposix.dup(fd1, False)
+ assert rposix.get_inheritable(fd4) == False
+ rposix.dup2(fd2, fd4, False)
+ assert rposix.get_inheritable(fd4) == False
+ rposix.dup2(fd2, fd3, True)
+ assert rposix.get_inheritable(fd3) == True
+ os.close(fd1)
+ os.close(fd2)
+ os.close(fd3)
+ os.close(fd4)
+
def test_sync():
if sys.platform != 'win32':
rposix.sync()
More information about the pypy-commit
mailing list