Author: Armin Rigo <ar...@tunes.org> Branch: release-pypy2.7-5.x Changeset: r88251:c03abff8ff75 Date: 2016-11-08 18:44 +0100 http://bitbucket.org/pypy/pypy/changeset/c03abff8ff75/
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() _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit