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