Author: Matti Picus <[email protected]>
Branch: msvc14
Changeset: r93775:2f7ecead192b
Date: 2018-02-06 12:02 +0100
http://bitbucket.org/pypy/pypy/changeset/2f7ecead192b/

Log:    make validate_fd into a context manager FdValidator(fd) for msvc

diff --git a/pypy/module/__pypy__/__init__.py b/pypy/module/__pypy__/__init__.py
--- a/pypy/module/__pypy__/__init__.py
+++ b/pypy/module/__pypy__/__init__.py
@@ -87,7 +87,6 @@
         'get_hidden_tb'             : 'interp_magic.get_hidden_tb',
         'lookup_special'            : 'interp_magic.lookup_special',
         'do_what_I_mean'            : 'interp_magic.do_what_I_mean',
-        'validate_fd'               : 'interp_magic.validate_fd',
         'resizelist_hint'           : 'interp_magic.resizelist_hint',
         'newlist_hint'              : 'interp_magic.newlist_hint',
         'add_memory_pressure'       : 'interp_magic.add_memory_pressure',
diff --git a/pypy/module/__pypy__/interp_magic.py 
b/pypy/module/__pypy__/interp_magic.py
--- a/pypy/module/__pypy__/interp_magic.py
+++ b/pypy/module/__pypy__/interp_magic.py
@@ -107,14 +107,6 @@
         raise oefmt(space.w_TypeError, "expecting dict or list or set object")
     return space.newtext(name)
 
-
-@unwrap_spec(fd='c_int')
-def validate_fd(space, fd):
-    try:
-        rposix.validate_fd(fd)
-    except OSError as e:
-        raise wrap_oserror(space, e)
-
 def get_console_cp(space):
     from rpython.rlib import rwin32    # Windows only
     return space.newtuple([
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -30,7 +30,7 @@
 from pypy.module.__builtin__.interp_classobj import W_ClassObject
 from pypy.module.micronumpy.base import W_NDimArray
 from rpython.rlib.entrypoint import entrypoint_lowlevel
-from rpython.rlib.rposix import is_valid_fd, validate_fd
+from rpython.rlib.rposix import is_valid_fd, FdValidator
 from rpython.rlib.unroll import unrolling_iterable
 from rpython.rlib.objectmodel import specialize
 from pypy.module import exceptions
@@ -96,25 +96,31 @@
     dash = ''
 
 def fclose(fp):
-    if not is_valid_fd(c_fileno(fp)):
+    try:
+        with FdValidator(c_fileno(fp)):
+            return c_fclose(fp)
+    except IOError:
         return -1
-    return c_fclose(fp)
 
 def fwrite(buf, sz, n, fp):
-    validate_fd(c_fileno(fp))
-    return c_fwrite(buf, sz, n, fp)
+    with FdValidator(c_fileno(fp)):
+        return c_fwrite(buf, sz, n, fp)
 
 def fread(buf, sz, n, fp):
-    validate_fd(c_fileno(fp))
-    return c_fread(buf, sz, n, fp)
+    with FdValidator(c_fileno(fp)):
+        return c_fread(buf, sz, n, fp)
 
 _feof = rffi.llexternal('feof', [FILEP], rffi.INT)
 def feof(fp):
-    validate_fd(c_fileno(fp))
-    return _feof(fp)
+    with FdValidator(c_fileno(fp)):
+        return _feof(fp)
 
 def is_valid_fp(fp):
-    return is_valid_fd(c_fileno(fp))
+    try:
+        with FdValidator(c_fileno(fp)):
+            return 1
+    except IOError:
+        return 0
 
 pypy_decl = 'pypy_decl.h'
 udir.join(pypy_decl).write("/* Will be filled later */\n")
diff --git a/pypy/module/posix/app_posix.py b/pypy/module/posix/app_posix.py
--- a/pypy/module/posix/app_posix.py
+++ b/pypy/module/posix/app_posix.py
@@ -1,7 +1,6 @@
 # NOT_RPYTHON
 
 from _structseq import structseqtype, structseqfield
-from __pypy__ import validate_fd
 
 # XXX we need a way to access the current module's globals more directly...
 import sys
@@ -80,25 +79,29 @@
     f_flag = structseqfield(8)
     f_namemax = structseqfield(9)
 
+# Capture file.fdopen at import time, as some code replaces
+# __builtins__.file with a custom function.
+_fdopen = file.fdopen
+
 if osname == 'posix':
     # POSIX: we want to check the file descriptor when fdopen() is called,
     # not later when we read or write data.  So we call fstat(), letting
     # it raise if fd is invalid.
-    _validate_fd = posix.fstat
+     def fdopen(fd, mode='r', buffering=-1):
+        """fdopen(fd [, mode='r' [, buffering]]) -> file_object
+
+        Return an open file object connected to a file descriptor."""
+        posix.fstat(fd)
+        return _fdopen(fd, mode, buffering)
+
 else:
-    _validate_fd = validate_fd
+     def fdopen(fd, mode='r', buffering=-1):
+        """fdopen(fd [, mode='r' [, buffering]]) -> file_object
 
-# Capture file.fdopen at import time, as some code replaces
-# __builtins__.file with a custom function.
-_fdopen = file.fdopen
-
-def fdopen(fd, mode='r', buffering=-1):
-    """fdopen(fd [, mode='r' [, buffering]]) -> file_object
-
-    Return an open file object connected to a file descriptor."""
-    _validate_fd(fd)
-    return _fdopen(fd, mode, buffering)
-
+        Return an open file object connected to a file descriptor."""
+        from rpython.rlib.rposix import FdValidator
+        with FdValidator(fd):
+            return _fdopen(fd, mode, buffering)
 
 def tmpfile():
     """Create a temporary file.
diff --git a/rpython/rlib/rfile.py b/rpython/rlib/rfile.py
--- a/rpython/rlib/rfile.py
+++ b/rpython/rlib/rfile.py
@@ -173,10 +173,10 @@
 
 def create_fdopen_rfile(fd, mode="r", buffering=-1):
     newmode = _sanitize_mode(mode)
-    rposix.validate_fd(fd)
     ll_mode = rffi.str2charp(newmode)
     try:
-        ll_file = c_fdopen(fd, ll_mode)
+        with rposix.FdValidator(fd):
+            ll_file = c_fdopen(fd, ll_mode)
         if not ll_file:
             errno = rposix.get_saved_errno()
             raise OSError(errno, os.strerror(errno))
diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py
--- a/rpython/rlib/rposix.py
+++ b/rpython/rlib/rposix.py
@@ -39,11 +39,11 @@
 
 if os.name == 'nt':
     if platform.name == 'msvc':
-        includes=['errno.h','stdio.h']
+        includes=['errno.h','stdio.h', 'stdlib.h']
     else:
         includes=['errno.h','stdio.h', 'stdint.h']
     separate_module_sources =['''
-        /* Lifted completely from CPython 3 Modules/posix_module.c */
+        /* Lifted completely from CPython 3 Modules/posixmodule.c */
         #if defined _MSC_VER && MSC_VER >= 1400 && _MSC_VER < 1900
         #include <malloc.h> /* for _msize */
         typedef struct {
@@ -96,12 +96,45 @@
             errno = EBADF;
             return 0;
         }
-        #else
-        RPY_EXTERN int
-        _PyVerify_fd(int fd)
+        RPY_EXTERN void* enter_suppress_iph(void) {return (void*)NULL};
+        RPY_EXTERN void exit_suppress_iph(void*) {};
+        #elif defined _MSC_VER
+        RPY_EXTERN int _PyVerify_fd(int fd)
         {
             return 1;
         }
+        static void __cdecl _Py_silent_invalid_parameter_handler(
+            wchar_t const* expression,
+            wchar_t const* function,
+            wchar_t const* file,
+            unsigned int line,
+            uintptr_t pReserved) {
+                wprintf(L"Invalid parameter detected in function %s."  
+                            L" File: %s Line: %d\\n", function, file, line);  
+                wprintf(L"Expression: %s\\n", expression);  
+        }
+
+        RPY_EXTERN void* enter_suppress_iph(void)
+        {
+            void* ret = 
_set_thread_local_invalid_parameter_handler(_Py_silent_invalid_parameter_handler);
+            /*fprintf(stdout, "setting %p returning %p\\n", 
(void*)_Py_silent_invalid_parameter_handler, ret);*/
+            return ret;
+        }
+        RPY_EXTERN void exit_suppress_iph(void*  old_handler)
+        {
+            void * ret;
+            _invalid_parameter_handler _handler = 
(_invalid_parameter_handler)old_handler;
+            ret = _set_thread_local_invalid_parameter_handler(_handler);
+            /*fprintf(stdout, "exiting, setting %p returning %p\\n", 
old_handler, ret);*/
+        }
+
+        #else
+        RPY_EXTERN int _PyVerify_fd(int fd)
+        {
+            return 1;
+        }
+        void* enter_suppress_iph(void) {return (void*) NULL};
+        void exit_suppress_iph(void*) {};
         #endif
     ''',]
     post_include_bits=['RPY_EXTERN int _PyVerify_fd(int);']
@@ -201,50 +234,6 @@
         else:
             rthread.tlfield_rpy_errno.setraw(_get_errno())
             # ^^^ keep fork() up-to-date too, below
-
-
-if os.name == 'nt':
-    is_valid_fd = jit.dont_look_inside(rffi.llexternal(
-        "_PyVerify_fd", [rffi.INT], rffi.INT,
-        compilation_info=errno_eci,
-        ))
-    @enforceargs(int)
-    def validate_fd(fd):
-        if not is_valid_fd(fd):
-            from errno import EBADF
-            raise OSError(EBADF, 'Bad file descriptor')
-
-    def _bound_for_write(fd, count):
-        if count > 32767 and c_isatty(fd):
-            # CPython Issue #11395, PyPy Issue #2636: the Windows console
-            # returns an error (12: not enough space error) on writing into
-            # stdout if stdout mode is binary and the length is greater than
-            # 66,000 bytes (or less, depending on heap usage).  Can't easily
-            # test that, because we need 'fd' to be non-redirected...
-            count = 32767
-        elif count > 0x7fffffff:
-            count = 0x7fffffff
-        return count
-else:
-    def is_valid_fd(fd):
-        return 1
-
-    @enforceargs(int)
-    def validate_fd(fd):
-        pass
-
-    def _bound_for_write(fd, count):
-        return count
-
-def closerange(fd_low, fd_high):
-    # this behaves like os.closerange() from Python 2.6.
-    for fd in xrange(fd_low, fd_high):
-        try:
-            if is_valid_fd(fd):
-                os.close(fd)
-        except OSError:
-            pass
-
 if _WIN32:
     includes = ['io.h', 'sys/utime.h', 'sys/types.h', 'process.h', 'time.h']
     libraries = []
@@ -266,11 +255,80 @@
     if sys.platform.startswith('freebsd') or 
sys.platform.startswith('openbsd'):
         includes.append('sys/ttycom.h')
     libraries = ['util']
+
 eci = ExternalCompilationInfo(
     includes=includes,
     libraries=libraries,
 )
 
+def external(name, args, result, compilation_info=eci, **kwds):
+    return rffi.llexternal(name, args, result,
+                           compilation_info=compilation_info, **kwds)
+
+
+if os.name == 'nt':
+    is_valid_fd = jit.dont_look_inside(external("_PyVerify_fd", [rffi.INT], 
+        rffi.INT, compilation_info=errno_eci,
+        ))
+    c_enter_suppress_iph = jit.dont_look_inside(external("enter_suppress_iph",
+                                  [], rffi.VOIDP, compilation_info=errno_eci))
+    c_exit_suppress_iph = jit.dont_look_inside(external("exit_suppress_iph",
+                                  [rffi.VOIDP], lltype.Void,
+                                  compilation_info=errno_eci))
+
+    @enforceargs(int)
+    def _validate_fd(fd):
+        if not is_valid_fd(fd):
+            from errno import EBADF
+            raise OSError(EBADF, 'Bad file descriptor')
+
+    class FdValidator(object):
+
+        def __init__(self, fd):
+            _validate_fd(fd)
+
+        def __enter__(self):
+            self.invalid_param_hndlr = c_enter_suppress_iph()
+            return self
+
+        def __exit__(self, *args):
+            c_exit_suppress_iph(self.invalid_param_hndlr)
+
+    def _bound_for_write(fd, count):
+        if count > 32767 and c_isatty(fd):
+            # CPython Issue #11395, PyPy Issue #2636: the Windows console
+            # returns an error (12: not enough space error) on writing into
+            # stdout if stdout mode is binary and the length is greater than
+            # 66,000 bytes (or less, depending on heap usage).  Can't easily
+            # test that, because we need 'fd' to be non-redirected...
+            count = 32767
+        elif count > 0x7fffffff:
+            count = 0x7fffffff
+        return count
+else:
+    class FdValidator(object):
+
+        def __init__(self, fd):
+            pass
+
+        def __enter__(self):
+            return self
+
+        def __exit__(self, *args):
+            pass
+
+    def _bound_for_write(fd, count):
+        return count
+
+def closerange(fd_low, fd_high):
+    # this behaves like os.closerange() from Python 2.6.
+    for fd in xrange(fd_low, fd_high):
+        try:
+            with FdValidator(fd):
+                os.close(fd)
+        except OSError:
+            pass
+
 class CConfig:
     _compilation_info_ = eci
     SEEK_SET = rffi_platform.DefinedConstantInteger('SEEK_SET')
@@ -323,10 +381,6 @@
 config = rffi_platform.configure(CConfig)
 globals().update(config)
 
-def external(name, args, result, compilation_info=eci, **kwds):
-    return rffi.llexternal(name, args, result,
-                           compilation_info=compilation_info, **kwds)
-
 # For now we require off_t to be the same size as LONGLONG, which is the
 # interface required by callers of functions that thake an argument of type
 # off_t.
@@ -418,12 +472,12 @@
     return result
 
 def _dup(fd, inheritable=True):
-    validate_fd(fd)
-    if inheritable:
-        res = c_dup(fd)
-    else:
-        res = c_dup_noninheritable(fd)
-    return res
+    with FdValidator(fd):
+        if inheritable:
+            res = c_dup(fd)
+        else:
+            res = c_dup_noninheritable(fd)
+        return res
 
 @replace_os_function('dup')
 def dup(fd, inheritable=True):
@@ -432,12 +486,12 @@
 
 @replace_os_function('dup2')
 def dup2(fd, newfd, inheritable=True):
-    validate_fd(fd)
-    if inheritable:
-        res = c_dup2(fd, newfd)
-    else:
-        res = c_dup2_noninheritable(fd, newfd)
-    handle_posix_error('dup2', res)
+    with FdValidator(fd):
+        if inheritable:
+            res = c_dup2(fd, newfd)
+        else:
+            res = c_dup2_noninheritable(fd, newfd)
+        handle_posix_error('dup2', res)
 
 #___________________________________________________________________
 
@@ -465,25 +519,26 @@
 def read(fd, count):
     if count < 0:
         raise OSError(errno.EINVAL, None)
-    validate_fd(fd)
-    with rffi.scoped_alloc_buffer(count) as buf:
-        void_buf = rffi.cast(rffi.VOIDP, buf.raw)
-        got = handle_posix_error('read', c_read(fd, void_buf, count))
-        return buf.str(got)
+    with FdValidator(fd):
+        with rffi.scoped_alloc_buffer(count) as buf:
+            void_buf = rffi.cast(rffi.VOIDP, buf.raw)
+            got = handle_posix_error('read', c_read(fd, void_buf, count))
+            return buf.str(got)
 
 @replace_os_function('write')
 @enforceargs(int, None)
 def write(fd, data):
     count = len(data)
-    validate_fd(fd)
-    count = _bound_for_write(fd, count)
-    with rffi.scoped_nonmovingbuffer(data) as buf:
-        return handle_posix_error('write', c_write(fd, buf, count))
+    with FdValidator(fd):
+        count = _bound_for_write(fd, count)
+        with rffi.scoped_nonmovingbuffer(data) as buf:
+            ret = c_write(fd, buf, count)
+            return handle_posix_error('write', ret)
 
 @replace_os_function('close')
 def close(fd):
-    validate_fd(fd)
-    handle_posix_error('close', c_close(fd))
+    with FdValidator(fd):
+        handle_posix_error('close', c_close(fd))
 
 c_lseek = external('_lseeki64' if _WIN32 else 'lseek',
                    [rffi.INT, rffi.LONGLONG, rffi.INT], rffi.LONGLONG,
@@ -491,15 +546,15 @@
 
 @replace_os_function('lseek')
 def lseek(fd, pos, how):
-    validate_fd(fd)
-    if SEEK_SET is not None:
-        if how == 0:
-            how = SEEK_SET
-        elif how == 1:
-            how = SEEK_CUR
-        elif how == 2:
-            how = SEEK_END
-    return handle_posix_error('lseek', c_lseek(fd, pos, how))
+    with FdValidator(fd):
+        if SEEK_SET is not None:
+            if how == 0:
+                how = SEEK_SET
+            elif how == 1:
+                how = SEEK_CUR
+            elif how == 2:
+                how = SEEK_END
+        return handle_posix_error('lseek', c_lseek(fd, pos, how))
 
 if not _WIN32:
     c_pread = external('pread',
@@ -513,7 +568,6 @@
     def pread(fd, count, offset):
         if count < 0:
             raise OSError(errno.EINVAL, None)
-        validate_fd(fd)
         with rffi.scoped_alloc_buffer(count) as buf:
             void_buf = rffi.cast(rffi.VOIDP, buf.raw)
             return buf.str(handle_posix_error('pread', c_pread(fd, void_buf, 
count, offset)))
@@ -521,7 +575,6 @@
     @enforceargs(int, None, None)
     def pwrite(fd, data, offset):
         count = len(data)
-        validate_fd(fd)
         with rffi.scoped_nonmovingbuffer(data) as buf:
             return handle_posix_error('pwrite', c_pwrite(fd, buf, count, 
offset))
 
@@ -532,7 +585,6 @@
 
         @enforceargs(int, None, None)
         def posix_fallocate(fd, offset, length):
-            validate_fd(fd)
             return handle_posix_error('posix_fallocate', c_posix_fallocate(fd, 
offset, length))
 
     if HAVE_FADVISE:
@@ -554,7 +606,6 @@
 
         @enforceargs(int, None, None, int)
         def posix_fadvise(fd, offset, length, advice):
-            validate_fd(fd)
             error = c_posix_fadvise(fd, offset, length, advice)
             error = widen(error)
             if error != 0:
@@ -565,7 +616,6 @@
             save_err=rffi.RFFI_SAVE_ERRNO)
     @enforceargs(int, None, None)
     def lockf(fd, cmd, length):
-        validate_fd(fd)
         return handle_posix_error('lockf', c_lockf(fd, cmd, length))
 
 c_ftruncate = external('ftruncate', [rffi.INT, rffi.LONGLONG], rffi.INT,
@@ -579,18 +629,18 @@
 
 @replace_os_function('ftruncate')
 def ftruncate(fd, length):
-    validate_fd(fd)
-    handle_posix_error('ftruncate', c_ftruncate(fd, length))
+    with FdValidator(fd):
+        handle_posix_error('ftruncate', c_ftruncate(fd, length))
 
 @replace_os_function('fsync')
 def fsync(fd):
-    validate_fd(fd)
-    handle_posix_error('fsync', c_fsync(fd))
+    with FdValidator(fd):
+        handle_posix_error('fsync', c_fsync(fd))
 
 @replace_os_function('fdatasync')
 def fdatasync(fd):
-    validate_fd(fd)
-    handle_posix_error('fdatasync', c_fdatasync(fd))
+    with FdValidator(fd):
+        handle_posix_error('fdatasync', c_fdatasync(fd))
 
 def sync():
     c_sync()
@@ -657,8 +707,8 @@
 
 @replace_os_function('fchdir')
 def fchdir(fd):
-    validate_fd(fd)
-    handle_posix_error('fchdir', c_fchdir(fd))
+    with FdValidator(fd):
+        handle_posix_error('fchdir', c_fchdir(fd))
 
 @replace_os_function('access')
 @specialize.argtype(0)
@@ -1098,9 +1148,10 @@
 
 @replace_os_function('isatty')
 def isatty(fd):
-    if not is_valid_fd(fd):
-        return False
-    return c_isatty(fd) != 0
+    print 'isatty'
+    with FdValidator(fd):
+        return c_isatty(fd) != 0
+    return False
 
 c_ttyname = external('ttyname', [lltype.Signed], rffi.CCHARP,
                      releasegil=False,
diff --git a/rpython/rlib/rwin32.py b/rpython/rlib/rwin32.py
--- a/rpython/rlib/rwin32.py
+++ b/rpython/rlib/rwin32.py
@@ -218,9 +218,9 @@
     _get_osfhandle = rffi.llexternal('_get_osfhandle', [rffi.INT], HANDLE)
 
     def get_osfhandle(fd):
-        from rpython.rlib.rposix import validate_fd
-        validate_fd(fd)
-        handle = _get_osfhandle(fd)
+        from rpython.rlib.rposix import FdValidator
+        with FdValidator(fd):
+            handle = _get_osfhandle(fd)
         if handle == INVALID_HANDLE_VALUE:
             raise WindowsError(ERROR_INVALID_HANDLE, "Invalid file handle")
         return handle
diff --git a/rpython/rlib/test/test_rwin32.py b/rpython/rlib/test/test_rwin32.py
--- a/rpython/rlib/test/test_rwin32.py
+++ b/rpython/rlib/test/test_rwin32.py
@@ -15,19 +15,6 @@
     py.test.raises(OSError, rwin32.get_osfhandle, fd)
     rwin32.get_osfhandle(0)
 
-def test_get_osfhandle_raising():
-    #try to test what kind of exception get_osfhandle raises w/out fd 
validation
-    py.test.skip('Crashes python')
-    fid = open(str(udir.join('validate_test.txt')), 'w')
-    fd = fid.fileno()
-    fid.close()
-    def validate_fd(fd):
-        return 1
-    _validate_fd = rwin32.validate_fd
-    rwin32.validate_fd = validate_fd
-    raises(WindowsError, rwin32.get_osfhandle, fd)
-    rwin32.validate_fd = _validate_fd
-
 def test_open_process():
     pid = rwin32.GetCurrentProcessId()
     assert pid != 0
diff --git a/rpython/translator/platform/windows.py 
b/rpython/translator/platform/windows.py
--- a/rpython/translator/platform/windows.py
+++ b/rpython/translator/platform/windows.py
@@ -427,10 +427,14 @@
         if len(headers_to_precompile)>0 and self.version >= 80:
             # at least from VS2013 onwards we need to include PCH
             # objects in the final link command
-            linkobjs = 'stdafx.obj @<<\n$(OBJECTS)\n<<'
+            linkobjs = 'stdafx.obj '
         else:
-            linkobjs = '@<<\n$(OBJECTS)\n<<'
-
+            linkobjs = ''
+        if len(' '.join(rel_ofiles)) > 2048:
+            # command line is limited in length, use a response file
+            linkobjs += '@<<\n$(OBJECTS)\n<<'
+        else:
+            linkobjs += '$(OBJECTS)'
         extra_deps = []
         if icon and not shared:
             extra_deps.append('icon.res')
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to