Author: Matti Picus <[email protected]>
Branch: memoryview-attributes
Changeset: r86373:6cb76ef9492b
Date: 2016-08-21 21:08 +1000
http://bitbucket.org/pypy/pypy/changeset/6cb76ef9492b/

Log:    merge default into branch

diff --git a/lib_pypy/resource.py b/lib_pypy/resource.py
--- a/lib_pypy/resource.py
+++ b/lib_pypy/resource.py
@@ -86,7 +86,11 @@
     if len(limits) != 2:
         raise ValueError("expected a tuple of 2 integers")
 
-    if lib.my_setrlimit(resource, limits[0], limits[1]) == -1:
+    # accept and round down floats, like CPython does
+    limit0 = int(limits[0])
+    limit1 = int(limits[1])
+
+    if lib.my_setrlimit(resource, limit0, limit1) == -1:
         if ffi.errno == EINVAL:
             raise ValueError("current limit exceeds maximum limit")
         elif ffi.errno == EPERM:
diff --git a/pypy/doc/faq.rst b/pypy/doc/faq.rst
--- a/pypy/doc/faq.rst
+++ b/pypy/doc/faq.rst
@@ -356,6 +356,11 @@
 that a C-level traceback is usually of no help at all in PyPy.
 Debugging PyPy can be annoying.
 
+`This is a clear and useful bug report.`__  (Admittedly, sometimes
+the problem is really hard to reproduce, but please try to.)
+
+.. __: 
https://bitbucket.org/pypy/pypy/issues/2363/segfault-in-gc-pinned-object-in
+
 In more details:
 
 * First, please give the exact PyPy version, and the OS.
diff --git a/pypy/interpreter/astcompiler/assemble.py 
b/pypy/interpreter/astcompiler/assemble.py
--- a/pypy/interpreter/astcompiler/assemble.py
+++ b/pypy/interpreter/astcompiler/assemble.py
@@ -387,7 +387,8 @@
     def _stacksize(self, blocks):
         """Compute co_stacksize."""
         for block in blocks:
-            block.initial_depth = 0
+            block.initial_depth = -99
+        blocks[0].initial_depth = 0
         # Assumes that it is sufficient to walk the blocks in 'post-order'.
         # This means we ignore all back-edges, but apart from that, we only
         # look into a block when all the previous blocks have been done.
@@ -406,8 +407,11 @@
 
     def _do_stack_depth_walk(self, block):
         depth = block.initial_depth
+        if depth == -99:     # this block is never reached, skip
+             return 0
         for instr in block.instructions:
             depth += _opcode_stack_effect(instr.opcode, instr.arg)
+            assert depth >= 0
             if depth >= self._max_depth:
                 self._max_depth = depth
             jump_op = instr.opcode
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -1707,6 +1707,23 @@
                 "Python int too large for C unsigned short")
         return value
 
+    def c_uid_t_w(self, w_obj):
+        # xxx assumes that uid_t and gid_t are a C unsigned int.
+        # Equivalent to space.c_uint_w(), with the exception that
+        # it also accepts -1 and converts that to UINT_MAX, which
+        # is (uid_t)-1.  And values smaller than -1 raise
+        # OverflowError, not ValueError.
+        try:
+            return self.c_uint_w(w_obj)
+        except OperationError as e:
+            if e.match(self, self.w_ValueError):
+                # ValueError: cannot convert negative integer to unsigned
+                if self.int_w(w_obj) == -1:
+                    return UINT_MAX
+                raise oefmt(self.w_OverflowError,
+                            "user/group id smaller than minimum (-1)")
+            raise
+
     def truncatedint_w(self, w_obj, allow_conversion=True):
         # Like space.gateway_int_w(), but return the integer truncated
         # instead of raising OverflowError.  For obscure cases only.
diff --git a/pypy/interpreter/gateway.py b/pypy/interpreter/gateway.py
--- a/pypy/interpreter/gateway.py
+++ b/pypy/interpreter/gateway.py
@@ -167,6 +167,9 @@
     def visit_c_ushort(self, el, app_sig):
         self.checked_space_method(el, app_sig)
 
+    def visit_c_uid_t(self, el, app_sig):
+        self.checked_space_method(el, app_sig)
+
     def visit_truncatedint_w(self, el, app_sig):
         self.checked_space_method(el, app_sig)
 
@@ -294,6 +297,9 @@
     def visit_c_ushort(self, typ):
         self.run_args.append("space.c_ushort_w(%s)" % (self.scopenext(),))
 
+    def visit_c_uid_t(self, typ):
+        self.run_args.append("space.c_uid_t_w(%s)" % (self.scopenext(),))
+
     def visit_truncatedint_w(self, typ):
         self.run_args.append("space.truncatedint_w(%s)" % (self.scopenext(),))
 
@@ -440,6 +446,9 @@
     def visit_c_ushort(self, typ):
         self.unwrap.append("space.c_ushort_w(%s)" % (self.nextarg(),))
 
+    def visit_c_uid_t(self, typ):
+        self.unwrap.append("space.c_uid_t_w(%s)" % (self.nextarg(),))
+
     def visit_truncatedint_w(self, typ):
         self.unwrap.append("space.truncatedint_w(%s)" % (self.nextarg(),))
 
@@ -587,7 +596,10 @@
 
         # First extract the signature from the (CPython-level) code object
         from pypy.interpreter import pycode
-        argnames, varargname, kwargname = 
pycode.cpython_code_signature(func.func_code)
+        sig = pycode.cpython_code_signature(func.func_code)
+        argnames = sig.argnames
+        varargname = sig.varargname
+        kwargname = sig.kwargname
         self._argnames = argnames
 
         if unwrap_spec is None:
@@ -611,7 +623,9 @@
         app_sig = SignatureBuilder(func)
 
         UnwrapSpec_Check(orig_sig).apply_over(unwrap_spec, app_sig)
-        self.sig = argnames, varargname, kwargname = app_sig.signature()
+        self.sig = app_sig.signature()
+        argnames = self.sig.argnames
+        varargname = self.sig.varargname
 
         self.minargs = len(argnames)
         if varargname:
@@ -942,7 +956,7 @@
                 defs_w.append(space.wrap(defaultval))
         if self._code._unwrap_spec:
             UNDEFINED = object()
-            alldefs_w = [UNDEFINED] * len(self._code.sig[0])
+            alldefs_w = [UNDEFINED] * len(self._code.sig.argnames)
             if defs_w:
                 alldefs_w[-len(defs_w):] = defs_w
             code = self._code
@@ -959,7 +973,7 @@
                     assert isinstance(w_default, W_Root)
                     assert argname.startswith('w_')
                     argname = argname[2:]
-                    j = self._code.sig[0].index(argname)
+                    j = self._code.sig.argnames.index(argname)
                     assert alldefs_w[j] in (UNDEFINED, None)
                     alldefs_w[j] = w_default
             first_defined = 0
diff --git a/pypy/interpreter/pycode.py b/pypy/interpreter/pycode.py
--- a/pypy/interpreter/pycode.py
+++ b/pypy/interpreter/pycode.py
@@ -37,7 +37,7 @@
 
 # cpython_code_signature helper
 def cpython_code_signature(code):
-    "([list-of-arg-names], vararg-name-or-None, kwarg-name-or-None)."
+    """Return a Signature instance."""
     argcount = code.co_argcount
     varnames = code.co_varnames
     assert argcount >= 0     # annotator hint
diff --git a/pypy/interpreter/signature.py b/pypy/interpreter/signature.py
--- a/pypy/interpreter/signature.py
+++ b/pypy/interpreter/signature.py
@@ -55,18 +55,3 @@
         if not isinstance(other, Signature):
             return NotImplemented
         return not self == other
-
-
-    # make it look tuply for its use in the annotator
-
-    def __len__(self):
-        return 3
-
-    def __getitem__(self, i):
-        if i == 0:
-            return self.argnames
-        if i == 1:
-            return self.varargname
-        if i == 2:
-            return self.kwargname
-        raise IndexError
\ No newline at end of file
diff --git a/pypy/interpreter/test/test_argument.py 
b/pypy/interpreter/test/test_argument.py
--- a/pypy/interpreter/test/test_argument.py
+++ b/pypy/interpreter/test/test_argument.py
@@ -46,13 +46,6 @@
         assert sig.find_argname("c") == 2
         assert sig.find_argname("d") == -1
 
-    def test_tuply(self):
-        sig = Signature(["a", "b", "c"], "d", "e")
-        x, y, z = sig
-        assert x == ["a", "b", "c"]
-        assert y == "d"
-        assert z == "e"
-
 class dummy_wrapped_dict(dict):
     def __nonzero__(self):
         raise NotImplementedError
diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py
--- a/pypy/interpreter/typedef.py
+++ b/pypy/interpreter/typedef.py
@@ -203,7 +203,8 @@
     name = func.__name__
     extra = ', '.join(extraargs)
     from pypy.interpreter import pycode
-    argnames, _, _ = pycode.cpython_code_signature(func.func_code)
+    sig = pycode.cpython_code_signature(func.func_code)
+    argnames = sig.argnames
     if use_closure:
         if argnames[1] == 'space':
             args = "closure, space, obj"
diff --git a/pypy/module/_cffi_backend/cdataobj.py 
b/pypy/module/_cffi_backend/cdataobj.py
--- a/pypy/module/_cffi_backend/cdataobj.py
+++ b/pypy/module/_cffi_backend/cdataobj.py
@@ -310,11 +310,15 @@
                             self.ctype.name, ct.name)
             #
             itemsize = ct.ctitem.size
-            if itemsize <= 0:
-                itemsize = 1
             with self as ptr1, w_other as ptr2:
                 diff = (rffi.cast(lltype.Signed, ptr1) -
-                        rffi.cast(lltype.Signed, ptr2)) // itemsize
+                        rffi.cast(lltype.Signed, ptr2))
+            if itemsize > 1:
+                if diff % itemsize:
+                    raise oefmt(space.w_ValueError,
+                        "pointer subtraction: the distance between the two "
+                        "pointers is not a multiple of the item size")
+                diff //= itemsize
             return space.wrap(diff)
         #
         return self._add_or_sub(w_other, -1)
diff --git a/pypy/module/_cffi_backend/misc.py 
b/pypy/module/_cffi_backend/misc.py
--- a/pypy/module/_cffi_backend/misc.py
+++ b/pypy/module/_cffi_backend/misc.py
@@ -253,6 +253,7 @@
     sandboxsafe=True)
 
 # split here for JIT backends that don't support floats/longlongs/etc.
[email protected]_look_inside
 def is_nonnull_longdouble(cdata):
     return _is_nonnull_longdouble(read_raw_longdouble_data(cdata))
 def is_nonnull_float(cdata, size):
diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py 
b/pypy/module/_cffi_backend/test/_backend_test_c.py
--- a/pypy/module/_cffi_backend/test/_backend_test_c.py
+++ b/pypy/module/_cffi_backend/test/_backend_test_c.py
@@ -576,6 +576,19 @@
     e = py.test.raises(TypeError, "q - a")
     assert str(e.value) == "cannot subtract cdata 'short *' and cdata 'int *'"
 
+def test_ptr_sub_unaligned():
+    BInt = new_primitive_type("int")
+    BIntPtr = new_pointer_type(BInt)
+    a = cast(BIntPtr, 1240)
+    for bi in range(1430, 1438):
+        b = cast(BIntPtr, bi)
+        if ((bi - 1240) % size_of_int()) == 0:
+            assert b - a == (bi - 1240) // size_of_int()
+            assert a - b == (1240 - bi) // size_of_int()
+        else:
+            py.test.raises(ValueError, "b - a")
+            py.test.raises(ValueError, "a - b")
+
 def test_cast_primitive_from_cdata():
     p = new_primitive_type("int")
     n = cast(p, cast(p, -42))
diff --git a/pypy/module/_cffi_backend/test/test_re_python.py 
b/pypy/module/_cffi_backend/test/test_re_python.py
--- a/pypy/module/_cffi_backend/test/test_re_python.py
+++ b/pypy/module/_cffi_backend/test/test_re_python.py
@@ -69,10 +69,13 @@
         sub_ffi.set_source('re_py_subsrc', None)
         sub_ffi.emit_python_code(str(tmpdir.join('re_py_subsrc.py')))
         #
-        space.appexec([space.wrap(str(tmpdir))], """(path):
-            import _cffi_backend     # force it to be initialized
-            import sys
-            sys.path.insert(0, path)
+        cls.w_fix_path = space.appexec([space.wrap(str(tmpdir))], """(path):
+            def fix_path(ignored=None):
+                import _cffi_backend     # force it to be initialized
+                import sys
+                if path not in sys.path:
+                    sys.path.insert(0, path)
+            return fix_path
         """)
 
     def teardown_method(self, meth):
@@ -86,17 +89,20 @@
 
 
     def test_constant_1(self):
+        self.fix_path()
         from re_python_pysrc import ffi
         assert ffi.integer_const('FOOBAR') == -42
         assert ffi.integer_const('FOOBAZ') == -43
 
     def test_large_constant(self):
+        self.fix_path()
         from re_python_pysrc import ffi
         assert ffi.integer_const('BIGPOS') == 420000000000
         assert ffi.integer_const('BIGNEG') == -420000000000
 
     def test_function(self):
         import _cffi_backend
+        self.fix_path()
         from re_python_pysrc import ffi
         lib = ffi.dlopen(self.extmod)
         assert lib.add42(-10) == 32
@@ -104,6 +110,7 @@
 
     def test_dlclose(self):
         import _cffi_backend
+        self.fix_path()
         from re_python_pysrc import ffi
         lib = ffi.dlopen(self.extmod)
         ffi.dlclose(lib)
@@ -115,17 +122,20 @@
             "library '%s' has been closed" % (self.extmod,))
 
     def test_constant_via_lib(self):
+        self.fix_path()
         from re_python_pysrc import ffi
         lib = ffi.dlopen(self.extmod)
         assert lib.FOOBAR == -42
         assert lib.FOOBAZ == -43
 
     def test_opaque_struct(self):
+        self.fix_path()
         from re_python_pysrc import ffi
         ffi.cast("struct foo_s *", 0)
         raises(TypeError, ffi.new, "struct foo_s *")
 
     def test_nonopaque_struct(self):
+        self.fix_path()
         from re_python_pysrc import ffi
         for p in [ffi.new("struct bar_s *", [5, b"foobar"]),
                   ffi.new("bar_t *", [5, b"foobar"])]:
@@ -134,12 +144,14 @@
             assert p.a[5] == ord('r')
 
     def test_enum(self):
+        self.fix_path()
         from re_python_pysrc import ffi
         assert ffi.integer_const("BB") == 1
         e = ffi.cast("enum foo_e", 2)
         assert ffi.string(e) == "CC"
 
     def test_include_1(self):
+        self.fix_path()
         from re_py_subsrc import ffi
         assert ffi.integer_const('FOOBAR') == -42
         assert ffi.integer_const('FOOBAZ') == -43
@@ -153,6 +165,7 @@
         assert p.a[4] == ord('a')
 
     def test_global_var(self):
+        self.fix_path()
         from re_python_pysrc import ffi
         lib = ffi.dlopen(self.extmod)
         assert lib.globalvar42 == 1234
@@ -163,24 +176,28 @@
         assert lib.globalvar42 == 1238
 
     def test_global_const_int(self):
+        self.fix_path()
         from re_python_pysrc import ffi
         lib = ffi.dlopen(self.extmod)
         assert lib.globalconst42 == 4321
         raises(AttributeError, ffi.addressof, lib, 'globalconst42')
 
     def test_global_const_nonint(self):
+        self.fix_path()
         from re_python_pysrc import ffi
         lib = ffi.dlopen(self.extmod)
         assert ffi.string(lib.globalconsthello, 8) == "hello"
         raises(AttributeError, ffi.addressof, lib, 'globalconsthello')
 
     def test_rtld_constants(self):
+        self.fix_path()
         from re_python_pysrc import ffi
         ffi.RTLD_NOW    # check that we have the attributes
         ffi.RTLD_LAZY
         ffi.RTLD_GLOBAL
 
     def test_no_such_function_or_global_var(self):
+        self.fix_path()
         from re_python_pysrc import ffi
         lib = ffi.dlopen(self.extmod)
         e = raises(ffi.error, getattr, lib, 'no_such_function')
diff --git a/pypy/module/_jitlog/test/test__jitlog.py 
b/pypy/module/_jitlog/test/test__jitlog.py
--- a/pypy/module/_jitlog/test/test__jitlog.py
+++ b/pypy/module/_jitlog/test/test__jitlog.py
@@ -10,10 +10,10 @@
 
     def setup_class(cls):
         cls.w_tmpfilename = cls.space.wrap(str(udir.join('test__jitlog.1')))
-        cls.w_mark_header = cls.space.wrap(jl.MARK_JITLOG_HEADER)
-        cls.w_version = cls.space.wrap(jl.JITLOG_VERSION_16BIT_LE)
+        cls.w_mark_header = cls.space.newbytes(jl.MARK_JITLOG_HEADER)
+        cls.w_version = cls.space.newbytes(jl.JITLOG_VERSION_16BIT_LE)
         cls.w_is_32bit = cls.space.wrap(sys.maxint == 2**31-1)
-        cls.w_machine = cls.space.wrap(platform.machine())
+        cls.w_machine = cls.space.newbytes(platform.machine())
         cls.w_resops = cls.space.newdict()
         space = cls.space
         for key, value in opname.items():
@@ -48,5 +48,3 @@
                 assert opnum in self.resops
                 # the name must equal
                 assert self.resops[opnum] == opname
-
-
diff --git a/pypy/module/_multibytecodec/src/cjkcodecs/cjkcodecs.h 
b/pypy/module/_multibytecodec/src/cjkcodecs/cjkcodecs.h
--- a/pypy/module/_multibytecodec/src/cjkcodecs/cjkcodecs.h
+++ b/pypy/module/_multibytecodec/src/cjkcodecs/cjkcodecs.h
@@ -268,22 +268,26 @@
     min = 0;
     max = haystacksize;
 
-    for (pos = haystacksize >> 1; min != max; pos = (min + max) >> 1)
+    for (pos = haystacksize >> 1; min != max; pos = (min + max) >> 1) {
         if (value < haystack[pos].uniseq) {
-            if (max == pos) break;
-            else max = pos;
+            if (max != pos) {
+                max = pos;
+                continue;
+            }
         }
         else if (value > haystack[pos].uniseq) {
-            if (min == pos) break;
-            else min = pos;
+            if (min != pos) {
+                min = pos;
+                continue;
+            }
         }
-        else
-            break;
+        break;
+    }
 
-        if (value == haystack[pos].uniseq)
-            return haystack[pos].code;
-        else
-            return DBCINV;
+    if (value == haystack[pos].uniseq) {
+        return haystack[pos].code;
+    }
+    return DBCINV;
 }
 #endif
 
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
@@ -11,7 +11,7 @@
 from rpython.rtyper.annlowlevel import llhelper
 from rpython.rlib.objectmodel import we_are_translated, keepalive_until_here
 from rpython.rlib.objectmodel import dont_inline
-from rpython.rlib.rfile import (FILEP, c_fread, c_fclose, c_fwrite, 
+from rpython.rlib.rfile import (FILEP, c_fread, c_fclose, c_fwrite,
         c_fdopen, c_fileno,
         c_fopen)# for tests
 from rpython.translator import cdir
@@ -259,14 +259,14 @@
 
         # extract the signature from the (CPython-level) code object
         from pypy.interpreter import pycode
-        argnames, varargname, kwargname = 
pycode.cpython_code_signature(callable.func_code)
+        sig = pycode.cpython_code_signature(callable.func_code)
+        assert sig.argnames[0] == 'space'
+        self.argnames = sig.argnames[1:]
+        if gil == 'pygilstate_ensure':
+            assert self.argnames[-1] == 'previous_state'
+            del self.argnames[-1]
+        assert len(self.argnames) == len(self.argtypes)
 
-        assert argnames[0] == 'space'
-        if gil == 'pygilstate_ensure':
-            assert argnames[-1] == 'previous_state'
-            del argnames[-1]
-        self.argnames = argnames[1:]
-        assert len(self.argnames) == len(self.argtypes)
         self.gil = gil
         self.result_borrowed = result_borrowed
         self.result_is_ll = result_is_ll
diff --git a/pypy/module/posix/interp_posix.py 
b/pypy/module/posix/interp_posix.py
--- a/pypy/module/posix/interp_posix.py
+++ b/pypy/module/posix/interp_posix.py
@@ -4,7 +4,7 @@
 from rpython.rlib import rposix, rposix_stat
 from rpython.rlib import objectmodel, rurandom
 from rpython.rlib.objectmodel import specialize
-from rpython.rlib.rarithmetic import r_longlong, intmask
+from rpython.rlib.rarithmetic import r_longlong, intmask, r_uint
 from rpython.rlib.unroll import unrolling_iterable
 
 from pypy.interpreter.gateway import unwrap_spec
@@ -20,20 +20,21 @@
 
 c_int = "c_int"
 
-# CPython 2.7 semantics are too messy to follow exactly,
-# e.g. setuid(-2) works on 32-bit but not on 64-bit.  As a result,
-# we decided to just accept any 'int', i.e. any C signed long, and
-# check that they are in range(-2**31, 2**32).  In other words, we
-# accept any number that is either a signed or an unsigned C int.
-c_uid_t = int
-c_gid_t = int
-if sys.maxint == 2147483647:
-    def check_uid_range(space, num):
-        pass
-else:
-    def check_uid_range(space, num):
-        if num < -(1 << 31) or num >= (1 << 32):
-            raise oefmt(space.w_OverflowError, "integer out of range")
+# CPython 2.7 semantics used to be too messy, differing on 32-bit vs
+# 64-bit, but this was cleaned up in recent 2.7.x.  Now, any function
+# taking a uid_t or gid_t accepts numbers in range(-1, 2**32) as an
+# r_uint, with -1 being equivalent to 2**32-1.  Any function that
+# returns a uid_t or gid_t returns either an int or a long, depending
+# on whether it fits or not, but always positive.
+c_uid_t = 'c_uid_t'
+c_gid_t = 'c_uid_t'
+
+def wrap_uid(space, uid):
+    if uid <= r_uint(sys.maxint):
+        return space.wrap(intmask(uid))
+    else:
+        return space.wrap(uid)     # an unsigned number
+wrap_gid = wrap_uid
 
 def fsencode_w(space, w_obj):
     if space.isinstance_w(w_obj, space.w_unicode):
@@ -912,7 +913,7 @@
 
     Return the current process's user id.
     """
-    return space.wrap(os.getuid())
+    return wrap_uid(space, os.getuid())
 
 @unwrap_spec(arg=c_uid_t)
 def setuid(space, arg):
@@ -920,12 +921,10 @@
 
     Set the current process's user id.
     """
-    check_uid_range(space, arg)
     try:
         os.setuid(arg)
     except OSError as e:
         raise wrap_oserror(space, e)
-    return space.w_None
 
 @unwrap_spec(arg=c_uid_t)
 def seteuid(space, arg):
@@ -933,12 +932,10 @@
 
     Set the current process's effective user id.
     """
-    check_uid_range(space, arg)
     try:
         os.seteuid(arg)
     except OSError as e:
         raise wrap_oserror(space, e)
-    return space.w_None
 
 @unwrap_spec(arg=c_gid_t)
 def setgid(space, arg):
@@ -946,12 +943,10 @@
 
     Set the current process's group id.
     """
-    check_uid_range(space, arg)
     try:
         os.setgid(arg)
     except OSError as e:
         raise wrap_oserror(space, e)
-    return space.w_None
 
 @unwrap_spec(arg=c_gid_t)
 def setegid(space, arg):
@@ -959,12 +954,10 @@
 
     Set the current process's effective group id.
     """
-    check_uid_range(space, arg)
     try:
         os.setegid(arg)
     except OSError as e:
         raise wrap_oserror(space, e)
-    return space.w_None
 
 @unwrap_spec(path='str0')
 def chroot(space, path):
@@ -983,21 +976,21 @@
 
     Return the current process's group id.
     """
-    return space.wrap(os.getgid())
+    return wrap_gid(space, os.getgid())
 
 def getegid(space):
     """ getegid() -> gid
 
     Return the current process's effective group id.
     """
-    return space.wrap(os.getegid())
+    return wrap_gid(space, os.getegid())
 
 def geteuid(space):
     """ geteuid() -> euid
 
     Return the current process's effective user id.
     """
-    return space.wrap(os.geteuid())
+    return wrap_uid(space, os.geteuid())
 
 def getgroups(space):
     """ getgroups() -> list of group IDs
@@ -1008,7 +1001,7 @@
         list = os.getgroups()
     except OSError as e:
         raise wrap_oserror(space, e)
-    return space.newlist([space.wrap(e) for e in list])
+    return space.newlist([wrap_gid(space, e) for e in list])
 
 def setgroups(space, w_list):
     """ setgroups(list)
@@ -1017,9 +1010,7 @@
     """
     list = []
     for w_gid in space.unpackiterable(w_list):
-        gid = space.int_w(w_gid)
-        check_uid_range(space, gid)
-        list.append(gid)
+        list.append(space.c_uid_t_w(w_gid))
     try:
         os.setgroups(list[:])
     except OSError as e:
@@ -1093,13 +1084,10 @@
 
     Set the current process's real and effective user ids.
     """
-    check_uid_range(space, ruid)
-    check_uid_range(space, euid)
     try:
         os.setreuid(ruid, euid)
     except OSError as e:
         raise wrap_oserror(space, e)
-    return space.w_None
 
 @unwrap_spec(rgid=c_gid_t, egid=c_gid_t)
 def setregid(space, rgid, egid):
@@ -1107,13 +1095,10 @@
 
     Set the current process's real and effective group ids.
     """
-    check_uid_range(space, rgid)
-    check_uid_range(space, egid)
     try:
         os.setregid(rgid, egid)
     except OSError as e:
         raise wrap_oserror(space, e)
-    return space.w_None
 
 @unwrap_spec(pid=c_int)
 def getsid(space, pid):
@@ -1150,7 +1135,7 @@
         raise wrap_oserror(space, e)
     return space.wrap(pgid)
 
-@unwrap_spec(fd=c_int, pgid=c_gid_t)
+@unwrap_spec(fd=c_int, pgid=c_int)
 def tcsetpgrp(space, fd, pgid):
     """ tcsetpgrp(fd, pgid)
 
@@ -1170,9 +1155,9 @@
         (ruid, euid, suid) = os.getresuid()
     except OSError as e:
         raise wrap_oserror(space, e)
-    return space.newtuple([space.wrap(ruid),
-                           space.wrap(euid),
-                           space.wrap(suid)])
+    return space.newtuple([wrap_uid(space, ruid),
+                           wrap_uid(space, euid),
+                           wrap_uid(space, suid)])
 
 def getresgid(space):
     """ getresgid() -> (rgid, egid, sgid)
@@ -1183,9 +1168,9 @@
         (rgid, egid, sgid) = os.getresgid()
     except OSError as e:
         raise wrap_oserror(space, e)
-    return space.newtuple([space.wrap(rgid),
-                           space.wrap(egid),
-                           space.wrap(sgid)])
+    return space.newtuple([wrap_gid(space, rgid),
+                           wrap_gid(space, egid),
+                           wrap_gid(space, sgid)])
 
 @unwrap_spec(ruid=c_uid_t, euid=c_uid_t, suid=c_uid_t)
 def setresuid(space, ruid, euid, suid):
@@ -1284,8 +1269,6 @@
 @unwrap_spec(path='str0', uid=c_uid_t, gid=c_gid_t)
 def chown(space, path, uid, gid):
     """Change the owner and group id of path to the numeric uid and gid."""
-    check_uid_range(space, uid)
-    check_uid_range(space, gid)
     try:
         os.chown(path, uid, gid)
     except OSError as e:
@@ -1295,8 +1278,6 @@
 def lchown(space, path, uid, gid):
     """Change the owner and group id of path to the numeric uid and gid.
 This function will not follow symbolic links."""
-    check_uid_range(space, uid)
-    check_uid_range(space, gid)
     try:
         os.lchown(path, uid, gid)
     except OSError as e:
@@ -1307,8 +1288,6 @@
     """Change the owner and group id of the file given by file descriptor
 fd to the numeric uid and gid."""
     fd = space.c_filedescriptor_w(w_fd)
-    check_uid_range(space, uid)
-    check_uid_range(space, gid)
     try:
         os.fchown(fd, uid, gid)
     except OSError as e:
diff --git a/pypy/module/posix/test/test_posix2.py 
b/pypy/module/posix/test/test_posix2.py
--- a/pypy/module/posix/test/test_posix2.py
+++ b/pypy/module/posix/test/test_posix2.py
@@ -619,10 +619,12 @@
             assert os.geteuid() == self.geteuid
 
     if hasattr(os, 'setuid'):
+        @py.test.mark.skipif("sys.version_info < (2, 7, 4)")
         def test_os_setuid_error(self):
             os = self.posix
-            raises(OverflowError, os.setuid, -2**31-1)
+            raises(OverflowError, os.setuid, -2)
             raises(OverflowError, os.setuid, 2**32)
+            raises(OSError, os.setuid, -1)
 
     if hasattr(os, 'getgid'):
         def test_os_getgid(self):
@@ -665,10 +667,14 @@
             raises(OSError, os.getpgid, 1234567)
 
     if hasattr(os, 'setgid'):
+        @py.test.mark.skipif("sys.version_info < (2, 7, 4)")
         def test_os_setgid_error(self):
             os = self.posix
-            raises(OverflowError, os.setgid, -2**31-1)
+            raises(OverflowError, os.setgid, -2)
             raises(OverflowError, os.setgid, 2**32)
+            raises(OSError, os.setgid, -1)
+            raises(OSError, os.setgid, -1L)
+            raises(OSError, os.setgid, 2**32-1)
 
     if hasattr(os, 'getsid'):
         def test_os_getsid(self):
diff --git a/pypy/module/test_lib_pypy/test_resource.py 
b/pypy/module/test_lib_pypy/test_resource.py
--- a/pypy/module/test_lib_pypy/test_resource.py
+++ b/pypy/module/test_lib_pypy/test_resource.py
@@ -45,5 +45,8 @@
 
 def test_setrlimit():
     # minimal "does not crash" test
-    x = resource.getrlimit(resource.RLIMIT_CPU)
-    resource.setrlimit(resource.RLIMIT_CPU, x)
+    x, y = resource.getrlimit(resource.RLIMIT_CPU)
+    resource.setrlimit(resource.RLIMIT_CPU, (x, y))
+    x += 0.2
+    y += 0.3
+    resource.setrlimit(resource.RLIMIT_CPU, (x, y))    # truncated to ints
diff --git a/pypy/objspace/std/mapdict.py b/pypy/objspace/std/mapdict.py
--- a/pypy/objspace/std/mapdict.py
+++ b/pypy/objspace/std/mapdict.py
@@ -221,7 +221,6 @@
         stack_index = 0
         while True:
             current = self
-            number_to_readd = 0
             number_to_readd, attr = self._find_branch_to_move_into(name, index)
             # we found the attributes further up, need to save the
             # previous values of the attributes we passed
diff --git a/pypy/tool/pytest/genreportdata.py 
b/pypy/tool/pytest/genreportdata.py
--- a/pypy/tool/pytest/genreportdata.py
+++ b/pypy/tool/pytest/genreportdata.py
@@ -17,7 +17,7 @@
             resultwc = py.path.svnwc(testresultdir)
             print "updating", resultwc
             resultwc.update()
-        except KeyboardInterrupt as RuntimeError:
+        except (KeyboardInterrupt, RuntimeError):
             raise
         except Exception as e: #py.process.ExecutionFailed,e:
             print >> sys.stderr, "Warning: ",e #Subversion update failed"
diff --git a/requirements.txt b/requirements.txt
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,3 +1,5 @@
+cffi>=1.4.0
+
 # hypothesis is used for test generation on untranslated tests
 hypothesis
 enum34>=1.1.2
diff --git a/rpython/jit/metainterp/compile.py 
b/rpython/jit/metainterp/compile.py
--- a/rpython/jit/metainterp/compile.py
+++ b/rpython/jit/metainterp/compile.py
@@ -1051,8 +1051,9 @@
     metainterp_sd = metainterp.staticdata
     jitdriver_sd = metainterp.jitdriver_sd
     #
+    jd_name = jitdriver_sd.jitdriver.name
     metainterp_sd.jitlog.start_new_trace(metainterp_sd,
-            faildescr=resumekey, entry_bridge=False)
+            faildescr=resumekey, entry_bridge=False, jd_name=jd_name)
     #
     if isinstance(resumekey, ResumeAtPositionDescr):
         inline_short_preamble = False
diff --git a/rpython/jit/metainterp/logger.py b/rpython/jit/metainterp/logger.py
--- a/rpython/jit/metainterp/logger.py
+++ b/rpython/jit/metainterp/logger.py
@@ -98,6 +98,7 @@
     def log_abort_loop(self, trace, memo=None):
         debug_start("jit-abort-log")
         if not have_debug_prints():
+            debug_stop("jit-abort-log")
             return
         inputargs, operations = self._unpack_trace(trace)
         logops = self._log_operations(inputargs, operations, ops_offset=None,
diff --git a/rpython/jit/metainterp/test/support.py 
b/rpython/jit/metainterp/test/support.py
--- a/rpython/jit/metainterp/test/support.py
+++ b/rpython/jit/metainterp/test/support.py
@@ -64,6 +64,10 @@
     testself.all_graphs = graphs
     result_kind = history.getkind(graphs[0].getreturnvar().concretetype)[0]
 
+
+    class FakeJitDriver:
+        name = 'fakejitdriver'
+
     class FakeJitDriverSD:
         num_green_args = 0
         portal_graph = graphs[0]
@@ -72,6 +76,7 @@
         result_type = result_kind
         portal_runner_ptr = "???"
         vec = False
+        jitdriver = FakeJitDriver()
 
     stats = history.Stats(None)
     cpu = CPUClass(rtyper, stats, None, False)
diff --git a/rpython/rlib/rjitlog/rjitlog.py b/rpython/rlib/rjitlog/rjitlog.py
--- a/rpython/rlib/rjitlog/rjitlog.py
+++ b/rpython/rlib/rjitlog/rjitlog.py
@@ -212,7 +212,7 @@
         return method
     return decor
 
-JITLOG_VERSION = 1
+JITLOG_VERSION = 2
 JITLOG_VERSION_16BIT_LE = struct.pack("<H", JITLOG_VERSION)
 
 marks = [
@@ -331,7 +331,7 @@
     def finish(self):
         jitlog_teardown()
 
-    def start_new_trace(self, metainterp_sd, faildescr=None, 
entry_bridge=False):
+    def start_new_trace(self, metainterp_sd, faildescr=None, 
entry_bridge=False, jd_name=""):
         # even if the logger is not enabled, increment the trace id
         self.trace_id += 1
         if not jitlog_enabled():
@@ -345,6 +345,7 @@
         else:
             content.append(encode_str('loop'))
             content.append(encode_le_addr(int(entry_bridge)))
+        content.append(encode_str(jd_name))
         self._write_marked(MARK_START_TRACE, ''.join(content))
 
     def trace_aborted(self):
@@ -508,7 +509,9 @@
         """ an operation is written as follows:
             <marker> <opid (16 bit)> \
                      <len (32 bit)> \
-                     <res_val>,<arg_0>,...,<arg_n>,<descr>
+                     <res_val>,<arg_0>,...,<arg_n> \
+                     <descr>
+                     <failarg_0>,...<failarg_n>
             The marker indicates if the last argument is
             a descr or a normal argument.
         """
@@ -517,16 +520,21 @@
         le_opnum = encode_le_16bit(op.getopnum())
         str_res = self.var_to_str(op)
         line = ','.join([str_res] + str_args)
+        failargslist = op.getfailargs()
+        failargs = ''
+        if failargslist:
+            failargs = ','.join([self.var_to_str(farg) for farg in 
failargslist])
+        #
         if descr:
             descr_str = descr.repr_of_descr()
             line = line + ',' + descr_str
             string = encode_str(line)
             descr_number = compute_unique_id(descr)
             le_descr_number = encode_le_addr(descr_number)
-            return MARK_RESOP_DESCR, le_opnum + string + le_descr_number
+            return MARK_RESOP_DESCR, le_opnum + string + le_descr_number + 
encode_str(failargs)
         else:
             string = encode_str(line)
-            return MARK_RESOP, le_opnum + string
+            return MARK_RESOP, le_opnum + string + encode_str(failargs)
 
 
     def write_core_dump(self, operations, i, op, ops_offset):
@@ -578,6 +586,8 @@
         return ''.join(dump)
 
     def var_to_str(self, arg):
+        if arg is None:
+            return '-'
         try:
             mv = self.memo[arg]
         except KeyError:
diff --git a/rpython/rlib/rjitlog/test/test_jitlog.py 
b/rpython/rlib/rjitlog/test/test_jitlog.py
--- a/rpython/rlib/rjitlog/test/test_jitlog.py
+++ b/rpython/rlib/rjitlog/test/test_jitlog.py
@@ -48,7 +48,7 @@
         file.ensure()
         fd = file.open('wb')
         jl.jitlog_init(fd.fileno())
-        logger.start_new_trace(self.make_metainterp_sd())
+        logger.start_new_trace(self.make_metainterp_sd(), jd_name='jdname')
         log_trace = logger.log_trace(jl.MARK_TRACE, None, None)
         op = ResOperation(rop.DEBUG_MERGE_POINT, [ConstInt(0), ConstInt(0), 
ConstInt(0)])
         log_trace.write([], [op])
@@ -58,6 +58,7 @@
         is_32bit = chr(sys.maxint == 2**31-1)
         assert binary == (jl.MARK_START_TRACE) + jl.encode_le_addr(1) + \
                          jl.encode_str('loop') + jl.encode_le_addr(0) + \
+                         jl.encode_str('jdname') + \
                          (jl.MARK_TRACE) + jl.encode_le_addr(1) + \
                          (jl.MARK_INPUT_ARGS) + jl.encode_str('') + \
                          (jl.MARK_INIT_MERGE_POINT) + 
b'\x05\x00\x01s\x00i\x08s\x00i\x10s' + \
diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py
--- a/rpython/rlib/rposix.py
+++ b/rpython/rlib/rposix.py
@@ -96,12 +96,15 @@
             return 0;
         }
     ''',]
+    post_include_bits=['RPY_EXTERN int _PyVerify_fd(int);']
 else:
     separate_module_sources = []
+    post_include_bits = []
     includes=['errno.h','stdio.h']
 errno_eci = ExternalCompilationInfo(
     includes=includes,
     separate_module_sources=separate_module_sources,
+    post_include_bits=post_include_bits,
 )
 
 # Direct getters/setters, don't use directly!
@@ -251,6 +254,8 @@
                                    [('actime', rffi.INT),
                                     ('modtime', rffi.INT)])
     if not _WIN32:
+        UID_T = rffi_platform.SimpleType('uid_t', rffi.UINT)
+        GID_T = rffi_platform.SimpleType('gid_t', rffi.UINT)
         CLOCK_T = rffi_platform.SimpleType('clock_t', rffi.INT)
 
         TMS = rffi_platform.Struct(
@@ -1450,32 +1455,33 @@
 def setpgid(pid, gid):
     handle_posix_error('setpgid', c_setpgid(pid, gid))
 
-PID_GROUPS_T = rffi.CArrayPtr(rffi.PID_T)
-c_getgroups = external('getgroups', [rffi.INT, PID_GROUPS_T], rffi.INT,
-                       save_err=rffi.RFFI_SAVE_ERRNO)
-c_setgroups = external('setgroups', [rffi.SIZE_T, PID_GROUPS_T], rffi.INT,
-                       save_err=rffi.RFFI_SAVE_ERRNO)
-c_initgroups = external('initgroups', [rffi.CCHARP, rffi.PID_T], rffi.INT,
-                        save_err=rffi.RFFI_SAVE_ERRNO)
+if not _WIN32:
+    GID_GROUPS_T = rffi.CArrayPtr(GID_T)
+    c_getgroups = external('getgroups', [rffi.INT, GID_GROUPS_T], rffi.INT,
+                           save_err=rffi.RFFI_SAVE_ERRNO)
+    c_setgroups = external('setgroups', [rffi.SIZE_T, GID_GROUPS_T], rffi.INT,
+                           save_err=rffi.RFFI_SAVE_ERRNO)
+    c_initgroups = external('initgroups', [rffi.CCHARP, GID_T], rffi.INT,
+                            save_err=rffi.RFFI_SAVE_ERRNO)
 
 @replace_os_function('getgroups')
 def getgroups():
     n = handle_posix_error('getgroups',
-                           c_getgroups(0, lltype.nullptr(PID_GROUPS_T.TO)))
-    groups = lltype.malloc(PID_GROUPS_T.TO, n, flavor='raw')
+                           c_getgroups(0, lltype.nullptr(GID_GROUPS_T.TO)))
+    groups = lltype.malloc(GID_GROUPS_T.TO, n, flavor='raw')
     try:
         n = handle_posix_error('getgroups', c_getgroups(n, groups))
-        return [widen(groups[i]) for i in range(n)]
+        return [widen_gid(groups[i]) for i in range(n)]
     finally:
         lltype.free(groups, flavor='raw')
 
 @replace_os_function('setgroups')
 def setgroups(gids):
     n = len(gids)
-    groups = lltype.malloc(PID_GROUPS_T.TO, n, flavor='raw')
+    groups = lltype.malloc(GID_GROUPS_T.TO, n, flavor='raw')
     try:
         for i in range(n):
-            groups[i] = rffi.cast(rffi.PID_T, gids[i])
+            groups[i] = rffi.cast(GID_T, gids[i])
         handle_posix_error('setgroups', c_setgroups(n, groups))
     finally:
         lltype.free(groups, flavor='raw')
@@ -1526,104 +1532,115 @@
 
 #___________________________________________________________________
 
-c_getuid = external('getuid', [], rffi.INT, save_err=rffi.RFFI_SAVE_ERRNO)
-c_geteuid = external('geteuid', [], rffi.INT, save_err=rffi.RFFI_SAVE_ERRNO)
-c_setuid = external('setuid', [rffi.INT], rffi.INT,
-                    save_err=rffi.RFFI_SAVE_ERRNO)
-c_seteuid = external('seteuid', [rffi.INT], rffi.INT,
-                     save_err=rffi.RFFI_SAVE_ERRNO)
-c_getgid = external('getgid', [], rffi.INT, save_err=rffi.RFFI_SAVE_ERRNO)
-c_getegid = external('getegid', [], rffi.INT, save_err=rffi.RFFI_SAVE_ERRNO)
-c_setgid = external('setgid', [rffi.INT], rffi.INT,
-                    save_err=rffi.RFFI_SAVE_ERRNO)
-c_setegid = external('setegid', [rffi.INT], rffi.INT,
-                     save_err=rffi.RFFI_SAVE_ERRNO)
+if not _WIN32:
+    c_getuid = external('getuid', [], UID_T)
+    c_geteuid = external('geteuid', [], UID_T)
+    c_setuid = external('setuid', [UID_T], rffi.INT,
+                        save_err=rffi.RFFI_SAVE_ERRNO)
+    c_seteuid = external('seteuid', [UID_T], rffi.INT,
+                         save_err=rffi.RFFI_SAVE_ERRNO)
+    c_getgid = external('getgid', [], GID_T)
+    c_getegid = external('getegid', [], GID_T)
+    c_setgid = external('setgid', [GID_T], rffi.INT,
+                        save_err=rffi.RFFI_SAVE_ERRNO)
+    c_setegid = external('setegid', [GID_T], rffi.INT,
+                         save_err=rffi.RFFI_SAVE_ERRNO)
 
-@replace_os_function('getuid')
-def getuid():
-    return handle_posix_error('getuid', c_getuid())
+    def widen_uid(x):
+        return rffi.cast(lltype.Unsigned, x)
+    widen_gid = widen_uid
 
-@replace_os_function('geteuid')
-def geteuid():
-    return handle_posix_error('geteuid', c_geteuid())
+    # NOTE: the resulting type of functions that return a uid/gid is
+    # always Unsigned.  The argument type of functions that take a
+    # uid/gid should also be Unsigned.
 
-@replace_os_function('setuid')
-def setuid(uid):
-    handle_posix_error('setuid', c_setuid(uid))
+    @replace_os_function('getuid')
+    def getuid():
+        return widen_uid(c_getuid())
 
-@replace_os_function('seteuid')
-def seteuid(uid):
-    handle_posix_error('seteuid', c_seteuid(uid))
+    @replace_os_function('geteuid')
+    def geteuid():
+        return widen_uid(c_geteuid())
 
-@replace_os_function('getgid')
-def getgid():
-    return handle_posix_error('getgid', c_getgid())
+    @replace_os_function('setuid')
+    def setuid(uid):
+        handle_posix_error('setuid', c_setuid(uid))
 
-@replace_os_function('getegid')
-def getegid():
-    return handle_posix_error('getegid', c_getegid())
+    @replace_os_function('seteuid')
+    def seteuid(uid):
+        handle_posix_error('seteuid', c_seteuid(uid))
 
-@replace_os_function('setgid')
-def setgid(gid):
-    handle_posix_error('setgid', c_setgid(gid))
+    @replace_os_function('getgid')
+    def getgid():
+        return widen_gid(c_getgid())
 
-@replace_os_function('setegid')
-def setegid(gid):
-    handle_posix_error('setegid', c_setegid(gid))
+    @replace_os_function('getegid')
+    def getegid():
+        return widen_gid(c_getegid())
 
-c_setreuid = external('setreuid', [rffi.INT, rffi.INT], rffi.INT,
-                      save_err=rffi.RFFI_SAVE_ERRNO)
-c_setregid = external('setregid', [rffi.INT, rffi.INT], rffi.INT,
-                      save_err=rffi.RFFI_SAVE_ERRNO)
+    @replace_os_function('setgid')
+    def setgid(gid):
+        handle_posix_error('setgid', c_setgid(gid))
 
-@replace_os_function('setreuid')
-def setreuid(ruid, euid):
-    handle_posix_error('setreuid', c_setreuid(ruid, euid))
+    @replace_os_function('setegid')
+    def setegid(gid):
+        handle_posix_error('setegid', c_setegid(gid))
 
-@replace_os_function('setregid')
-def setregid(rgid, egid):
-    handle_posix_error('setregid', c_setregid(rgid, egid))
+    c_setreuid = external('setreuid', [UID_T, UID_T], rffi.INT,
+                          save_err=rffi.RFFI_SAVE_ERRNO)
+    c_setregid = external('setregid', [GID_T, GID_T], rffi.INT,
+                          save_err=rffi.RFFI_SAVE_ERRNO)
 
-c_getresuid = external('getresuid', [rffi.INTP] * 3, rffi.INT,
-                       save_err=rffi.RFFI_SAVE_ERRNO)
-c_getresgid = external('getresgid', [rffi.INTP] * 3, rffi.INT,
-                       save_err=rffi.RFFI_SAVE_ERRNO)
-c_setresuid = external('setresuid', [rffi.INT] * 3, rffi.INT,
-                       save_err=rffi.RFFI_SAVE_ERRNO)
-c_setresgid = external('setresgid', [rffi.INT] * 3, rffi.INT,
-                       save_err=rffi.RFFI_SAVE_ERRNO)
+    @replace_os_function('setreuid')
+    def setreuid(ruid, euid):
+        handle_posix_error('setreuid', c_setreuid(ruid, euid))
 
-@replace_os_function('getresuid')
-def getresuid():
-    out = lltype.malloc(rffi.INTP.TO, 3, flavor='raw')
-    try:
-        handle_posix_error('getresuid',
-                           c_getresuid(rffi.ptradd(out, 0),
-                                       rffi.ptradd(out, 1),
-                                       rffi.ptradd(out, 2)))
-        return (widen(out[0]), widen(out[1]), widen(out[2]))
-    finally:
-        lltype.free(out, flavor='raw')
+    @replace_os_function('setregid')
+    def setregid(rgid, egid):
+        handle_posix_error('setregid', c_setregid(rgid, egid))
 
-@replace_os_function('getresgid')
-def getresgid():
-    out = lltype.malloc(rffi.INTP.TO, 3, flavor='raw')
-    try:
-        handle_posix_error('getresgid',
-                           c_getresgid(rffi.ptradd(out, 0),
-                                       rffi.ptradd(out, 1),
-                                       rffi.ptradd(out, 2)))
-        return (widen(out[0]), widen(out[1]), widen(out[2]))
-    finally:
-        lltype.free(out, flavor='raw')
+    UID_T_P = lltype.Ptr(lltype.Array(UID_T, hints={'nolength': True}))
+    GID_T_P = lltype.Ptr(lltype.Array(GID_T, hints={'nolength': True}))
+    c_getresuid = external('getresuid', [UID_T_P] * 3, rffi.INT,
+                           save_err=rffi.RFFI_SAVE_ERRNO)
+    c_getresgid = external('getresgid', [GID_T_P] * 3, rffi.INT,
+                           save_err=rffi.RFFI_SAVE_ERRNO)
+    c_setresuid = external('setresuid', [UID_T] * 3, rffi.INT,
+                           save_err=rffi.RFFI_SAVE_ERRNO)
+    c_setresgid = external('setresgid', [GID_T] * 3, rffi.INT,
+                           save_err=rffi.RFFI_SAVE_ERRNO)
 
-@replace_os_function('setresuid')
-def setresuid(ruid, euid, suid):
-    handle_posix_error('setresuid', c_setresuid(ruid, euid, suid))
+    @replace_os_function('getresuid')
+    def getresuid():
+        out = lltype.malloc(UID_T_P.TO, 3, flavor='raw')
+        try:
+            handle_posix_error('getresuid',
+                               c_getresuid(rffi.ptradd(out, 0),
+                                           rffi.ptradd(out, 1),
+                                           rffi.ptradd(out, 2)))
+            return (widen_uid(out[0]), widen_uid(out[1]), widen_uid(out[2]))
+        finally:
+            lltype.free(out, flavor='raw')
 
-@replace_os_function('setresgid')
-def setresgid(rgid, egid, sgid):
-    handle_posix_error('setresgid', c_setresgid(rgid, egid, sgid))
+    @replace_os_function('getresgid')
+    def getresgid():
+        out = lltype.malloc(GID_T_P.TO, 3, flavor='raw')
+        try:
+            handle_posix_error('getresgid',
+                               c_getresgid(rffi.ptradd(out, 0),
+                                           rffi.ptradd(out, 1),
+                                           rffi.ptradd(out, 2)))
+            return (widen_gid(out[0]), widen_gid(out[1]), widen_gid(out[2]))
+        finally:
+            lltype.free(out, flavor='raw')
+
+    @replace_os_function('setresuid')
+    def setresuid(ruid, euid, suid):
+        handle_posix_error('setresuid', c_setresuid(ruid, euid, suid))
+
+    @replace_os_function('setresgid')
+    def setresgid(rgid, egid, sgid):
+        handle_posix_error('setresgid', c_setresgid(rgid, egid, sgid))
 
 #___________________________________________________________________
 
@@ -2046,3 +2063,40 @@
     def mknodat(path, mode, device, dir_fd=AT_FDCWD):
         error = c_mknodat(dir_fd, path, mode, device)
         handle_posix_error('mknodat', error)
+
+
+eci_inheritable = eci.merge(ExternalCompilationInfo(
+    separate_module_sources=["""
+RPY_EXTERN
+int rpy_set_inheritable(int fd, int inheritable)
+{
+    /* XXX minimal impl. XXX */
+    int request = inheritable ? FIONCLEX : FIOCLEX;
+    return ioctl(fd, request, NULL);
+}
+RPY_EXTERN
+int rpy_get_inheritable(int fd)
+{
+    int flags = fcntl(fd, F_GETFD, 0);
+    if (flags == -1)
+        return -1;
+    return !(flags & FD_CLOEXEC);
+}
+    """],
+    post_include_bits=['RPY_EXTERN int rpy_set_inheritable(int, int);']))
+
+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)
+
+def set_inheritable(fd, inheritable):
+    error = c_set_inheritable(fd, inheritable)
+    handle_posix_error('set_inheritable', error)
+
+def get_inheritable(fd):
+    res = c_get_inheritable(fd)
+    res = handle_posix_error('get_inheritable', res)
+    return res != 0
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
@@ -572,3 +572,12 @@
         os.close(dirfd)
     assert tmpdir.join('file').check(exists=False)
     assert tmpdir.join('file2').check(exists=True)
+
+def test_set_inheritable():
+    fd1, fd2 = os.pipe()
+    rposix.set_inheritable(fd1, True)
+    assert rposix.get_inheritable(fd1) == True
+    rposix.set_inheritable(fd1, False)
+    assert rposix.get_inheritable(fd1) == False
+    os.close(fd1)
+    os.close(fd2)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to