[pypy-commit] pypy errno-again: in-progress

arigo noreply at buildbot.pypy.org
Wed Jan 14 19:40:47 CET 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: errno-again
Changeset: r75333:73a539098acc
Date: 2015-01-14 19:40 +0100
http://bitbucket.org/pypy/pypy/changeset/73a539098acc/

Log:	in-progress

diff --git a/pypy/interpreter/error.py b/pypy/interpreter/error.py
--- a/pypy/interpreter/error.py
+++ b/pypy/interpreter/error.py
@@ -486,10 +486,10 @@
                              w_exception_class=w_exception_class)
 wrap_oserror._annspecialcase_ = 'specialize:arg(3)'
 
-def exception_from_errno(space, w_type):
-    from rpython.rlib.rposix import get_errno
+def exception_from_saved_errno(space, w_type):
+    from rpython.rlib.rposix import get_saved_errno
 
-    errno = get_errno()
+    errno = get_saved_errno()
     msg = os.strerror(errno)
     w_error = space.call_function(w_type, space.wrap(errno), space.wrap(msg))
     return OperationError(w_type, w_error)
diff --git a/pypy/module/__pypy__/interp_time.py b/pypy/module/__pypy__/interp_time.py
--- a/pypy/module/__pypy__/interp_time.py
+++ b/pypy/module/__pypy__/interp_time.py
@@ -1,7 +1,7 @@
 from __future__ import with_statement
 import sys
 
-from pypy.interpreter.error import exception_from_errno
+from pypy.interpreter.error import exception_from_saved_errno
 from pypy.interpreter.gateway import unwrap_spec
 from rpython.rtyper.lltypesystem import rffi, lltype
 from rpython.rtyper.tool import rffi_platform
@@ -48,11 +48,13 @@
 
     c_clock_gettime = rffi.llexternal("clock_gettime",
         [lltype.Signed, lltype.Ptr(TIMESPEC)], rffi.INT,
-        compilation_info=CConfig._compilation_info_, releasegil=False
+        compilation_info=CConfig._compilation_info_, releasegil=False,
+        save_err=rffi.RFFI_SAVE_ERRNO
     )
     c_clock_getres = rffi.llexternal("clock_getres",
         [lltype.Signed, lltype.Ptr(TIMESPEC)], rffi.INT,
-        compilation_info=CConfig._compilation_info_, releasegil=False
+        compilation_info=CConfig._compilation_info_, releasegil=False,
+        save_err=rffi.RFFI_SAVE_ERRNO
     )
 
     @unwrap_spec(clk_id="c_int")
@@ -60,7 +62,7 @@
         with lltype.scoped_alloc(TIMESPEC) as tp:
             ret = c_clock_gettime(clk_id, tp)
             if ret != 0:
-                raise exception_from_errno(space, space.w_IOError)
+                raise exception_from_saved_errno(space, space.w_IOError)
             return space.wrap(int(tp.c_tv_sec) + 1e-9 * int(tp.c_tv_nsec))
 
     @unwrap_spec(clk_id="c_int")
@@ -68,5 +70,5 @@
         with lltype.scoped_alloc(TIMESPEC) as tp:
             ret = c_clock_getres(clk_id, tp)
             if ret != 0:
-                raise exception_from_errno(space, space.w_IOError)
+                raise exception_from_saved_errno(space, space.w_IOError)
             return space.wrap(int(tp.c_tv_sec) + 1e-9 * int(tp.c_tv_nsec))
diff --git a/pypy/module/_rawffi/interp_rawffi.py b/pypy/module/_rawffi/interp_rawffi.py
--- a/pypy/module/_rawffi/interp_rawffi.py
+++ b/pypy/module/_rawffi/interp_rawffi.py
@@ -613,10 +613,10 @@
     return space.wrap(W_CDLL(space, name, cdll))
 
 def get_errno(space):
-    return space.wrap(rposix.get_errno())
+    return space.wrap(rposix.get_saved_errno())
 
 def set_errno(space, w_errno):
-    rposix.set_errno(space.int_w(w_errno))
+    rposix.set_saved_errno(space.int_w(w_errno))
 
 if sys.platform == 'win32':
     def get_last_error(space):
diff --git a/pypy/module/fcntl/interp_fcntl.py b/pypy/module/fcntl/interp_fcntl.py
--- a/pypy/module/fcntl/interp_fcntl.py
+++ b/pypy/module/fcntl/interp_fcntl.py
@@ -59,18 +59,24 @@
     return rffi.llexternal(name, args, result, compilation_info=CConfig._compilation_info_)
 
 _flock = lltype.Ptr(cConfig.flock)
-fcntl_int = external('fcntl', [rffi.INT, rffi.INT, rffi.INT], rffi.INT)
-fcntl_str = external('fcntl', [rffi.INT, rffi.INT, rffi.CCHARP], rffi.INT)
-fcntl_flock = external('fcntl', [rffi.INT, rffi.INT, _flock], rffi.INT)
-ioctl_int = external('ioctl', [rffi.INT, rffi.UINT, rffi.INT], rffi.INT)
-ioctl_str = external('ioctl', [rffi.INT, rffi.UINT, rffi.CCHARP], rffi.INT)
+fcntl_int = external('fcntl', [rffi.INT, rffi.INT, rffi.INT], rffi.INT,
+                     save_err=rffi.RFFI_SAVE_ERRNO)
+fcntl_str = external('fcntl', [rffi.INT, rffi.INT, rffi.CCHARP], rffi.INT,
+                     save_err=rffi.RFFI_SAVE_ERRNO)
+fcntl_flock = external('fcntl', [rffi.INT, rffi.INT, _flock], rffi.INT,
+                       save_err=rffi.RFFI_SAVE_ERRNO)
+ioctl_int = external('ioctl', [rffi.INT, rffi.UINT, rffi.INT], rffi.INT,
+                     save_err=rffi.RFFI_SAVE_ERRNO)
+ioctl_str = external('ioctl', [rffi.INT, rffi.UINT, rffi.CCHARP], rffi.INT,
+                     save_err=rffi.RFFI_SAVE_ERRNO)
 
 has_flock = cConfig.has_flock
 if has_flock:
-    c_flock = external('flock', [rffi.INT, rffi.INT], rffi.INT)
+    c_flock = external('flock', [rffi.INT, rffi.INT], rffi.INT,
+                       save_err=rffi.RFFI_SAVE_ERRNO)
 
 def _get_error(space, funcname):
-    errno = rposix.get_errno()
+    errno = rposix.get_saved_errno()
     return wrap_oserror(space, OSError(errno, funcname),
                         exception_name = 'w_IOError')
 
diff --git a/pypy/module/select/interp_epoll.py b/pypy/module/select/interp_epoll.py
--- a/pypy/module/select/interp_epoll.py
+++ b/pypy/module/select/interp_epoll.py
@@ -4,12 +4,13 @@
 
 from pypy.interpreter.baseobjspace import W_Root
 from pypy.interpreter.gateway import interp2app, unwrap_spec
-from pypy.interpreter.error import OperationError, exception_from_errno, oefmt
+from pypy.interpreter.error import OperationError, oefmt
+from pypy.interpreter.error import exception_from_saved_errno
 from pypy.interpreter.typedef import TypeDef, GetSetProperty
 from rpython.rtyper.lltypesystem import lltype, rffi
 from rpython.rtyper.tool import rffi_platform
 from rpython.rlib._rsocket_rffi import socketclose, FD_SETSIZE
-from rpython.rlib.rposix import get_errno
+from rpython.rlib.rposix import get_saved_errno
 from rpython.rlib.rarithmetic import intmask
 from rpython.translator.tool.cbuild import ExternalCompilationInfo
 
@@ -53,19 +54,22 @@
 EPOLL_CTL_DEL = cconfig["EPOLL_CTL_DEL"]
 
 epoll_create = rffi.llexternal(
-    "epoll_create", [rffi.INT], rffi.INT, compilation_info=eci
+    "epoll_create", [rffi.INT], rffi.INT, compilation_info=eci,
+    save_err=rffi.RFFI_SAVE_ERRNO
 )
 epoll_ctl = rffi.llexternal(
     "epoll_ctl",
     [rffi.INT, rffi.INT, rffi.INT, lltype.Ptr(epoll_event)],
     rffi.INT,
-    compilation_info=eci
+    compilation_info=eci,
+    save_err=rffi.RFFI_SAVE_ERRNO
 )
 epoll_wait = rffi.llexternal(
     "epoll_wait",
     [rffi.INT, rffi.CArrayPtr(epoll_event), rffi.INT, rffi.INT],
     rffi.INT,
     compilation_info=eci,
+    save_err=rffi.RFFI_SAVE_ERRNO
 )
 
 
@@ -82,7 +86,7 @@
                         "sizehint must be greater than zero, got %d", sizehint)
         epfd = epoll_create(sizehint)
         if epfd < 0:
-            raise exception_from_errno(space, space.w_IOError)
+            raise exception_from_saved_errno(space, space.w_IOError)
 
         return space.wrap(W_Epoll(space, epfd))
 
@@ -114,10 +118,10 @@
             rffi.setintfield(ev.c_data, 'c_fd', fd)
 
             result = epoll_ctl(self.epfd, ctl, fd, ev)
-            if ignore_ebadf and get_errno() == errno.EBADF:
+            if ignore_ebadf and get_saved_errno() == errno.EBADF:
                 result = 0
             if result < 0:
-                raise exception_from_errno(space, space.w_IOError)
+                raise exception_from_saved_errno(space, space.w_IOError)
 
     def descr_get_closed(self, space):
         return space.wrap(self.get_closed())
@@ -160,7 +164,7 @@
         with lltype.scoped_alloc(rffi.CArray(epoll_event), maxevents) as evs:
             nfds = epoll_wait(self.epfd, evs, maxevents, int(timeout))
             if nfds < 0:
-                raise exception_from_errno(space, space.w_IOError)
+                raise exception_from_saved_errno(space, space.w_IOError)
 
             elist_w = [None] * nfds
             for i in xrange(nfds):
diff --git a/pypy/module/select/interp_kqueue.py b/pypy/module/select/interp_kqueue.py
--- a/pypy/module/select/interp_kqueue.py
+++ b/pypy/module/select/interp_kqueue.py
@@ -1,5 +1,6 @@
 from pypy.interpreter.baseobjspace import W_Root
-from pypy.interpreter.error import OperationError, exception_from_errno, oefmt
+from pypy.interpreter.error import OperationError, oefmt
+from pypy.interpreter.error import exception_from_saved_errno
 from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault
 from pypy.interpreter.typedef import TypeDef, generic_new_descr, GetSetProperty
 from rpython.rlib._rsocket_rffi import socketclose
@@ -86,7 +87,8 @@
     "kqueue",
     [],
     rffi.INT,
-    compilation_info=eci
+    compilation_info=eci,
+    save_err=rffi.RFFI_SAVE_ERRNO
 )
 
 syscall_kevent = rffi.llexternal(
@@ -99,7 +101,8 @@
      lltype.Ptr(timespec)
     ],
     rffi.INT,
-    compilation_info=eci
+    compilation_info=eci,
+    save_err=rffi.RFFI_SAVE_ERRNO
 )
 
 
@@ -110,7 +113,7 @@
     def descr__new__(space, w_subtype):
         kqfd = syscall_kqueue()
         if kqfd < 0:
-            raise exception_from_errno(space, space.w_IOError)
+            raise exception_from_saved_errno(space, space.w_IOError)
         return space.wrap(W_Kqueue(space, kqfd))
 
     @unwrap_spec(fd=int)
@@ -198,7 +201,7 @@
                                           max_events,
                                           ptimeout)
                     if nfds < 0:
-                        raise exception_from_errno(space, space.w_IOError)
+                        raise exception_from_saved_errno(space, space.w_IOError)
                     else:
                         elist_w = [None] * nfds
                         for i in xrange(nfds):
diff --git a/pypy/module/signal/interp_signal.py b/pypy/module/signal/interp_signal.py
--- a/pypy/module/signal/interp_signal.py
+++ b/pypy/module/signal/interp_signal.py
@@ -5,7 +5,7 @@
 import os
 import errno
 
-from pypy.interpreter.error import OperationError, exception_from_errno
+from pypy.interpreter.error import OperationError, exception_from_saved_errno
 from pypy.interpreter.executioncontext import (AsyncAction, AbstractActionFlag,
     PeriodicAsyncAction)
 from pypy.interpreter.gateway import unwrap_spec
@@ -258,7 +258,7 @@
 def siginterrupt(space, signum, flag):
     check_signum_in_range(space, signum)
     if rffi.cast(lltype.Signed, c_siginterrupt(signum, flag)) < 0:
-        errno = rposix.get_errno()
+        errno = rposix.get_saved_errno()
         raise OperationError(space.w_RuntimeError, space.wrap(errno))
 
 
@@ -311,7 +311,7 @@
 
             ret = c_setitimer(which, new, old)
             if ret != 0:
-                raise exception_from_errno(space, get_itimer_error(space))
+                raise exception_from_saved_errno(space, get_itimer_error(space))
 
             return itimer_retval(space, old[0])
 
diff --git a/rpython/jit/backend/llsupport/test/zrpy_releasegil_test.py b/rpython/jit/backend/llsupport/test/zrpy_releasegil_test.py
--- a/rpython/jit/backend/llsupport/test/zrpy_releasegil_test.py
+++ b/rpython/jit/backend/llsupport/test/zrpy_releasegil_test.py
@@ -95,3 +95,24 @@
     def test_close_stack(self):
         self.run('close_stack')
         assert 'call_release_gil' in udir.join('TestCompileFramework.log').read()
+
+    ## def define_get_set_errno(self):
+
+    ##     c_strchr = rffi.llexternal('strchr', [rffi.CCHARP, lltype.Signed],
+    ##                                rffi.CCHARP, ...
+
+    ##     def before(n, x):
+    ##         return (n, None, None, None, None, None,
+    ##                 None, None, None, None, None, None)
+    ##     #
+    ##     def f(n, x, *args):
+    ##         a = rffi.str2charp(str(n))
+    ##         c_strchr(a, ord('0'))
+    ##         lltype.free(a, flavor='raw')
+    ##         n -= 1
+    ##         return (n, x) + args
+    ##     return before, f, None
+
+    ## def test_get_set_errno(self):
+    ##     self.run('get_set_errno')
+    ##     assert 'call_release_gil' in udir.join('TestCompileFramework.log').read()
diff --git a/rpython/jit/codewriter/call.py b/rpython/jit/codewriter/call.py
--- a/rpython/jit/codewriter/call.py
+++ b/rpython/jit/codewriter/call.py
@@ -10,6 +10,7 @@
     EffectInfo, CallInfoCollection)
 from rpython.rtyper.lltypesystem import lltype, llmemory
 from rpython.rtyper.typesystem import getfunctionptr
+from rpython.rlib import rposix
 from rpython.translator.backendopt.canraise import RaiseAnalyzer
 from rpython.translator.backendopt.writeanalyze import ReadWriteAnalyzer
 from rpython.translator.backendopt.graphanalyze import DependencyTracker
@@ -114,6 +115,10 @@
             if self.jitdriver_sd_from_portal_runner_ptr(funcptr) is not None:
                 return 'recursive'
             funcobj = funcptr._obj
+            assert (funcobj is not rposix._get_errno and
+                    funcobj is not rposix._set_errno), (
+                "the JIT must never come close to _get_errno() or _set_errno();"
+                " it should all be done at a lower level")
             if getattr(funcobj, 'graph', None) is None:
                 return 'residual'
             targetgraph = funcobj.graph
@@ -206,7 +211,7 @@
         # get the 'elidable' and 'loopinvariant' flags from the function object
         elidable = False
         loopinvariant = False
-        call_release_gil_target = llmemory.NULL
+        call_release_gil_target = EffectInfo._NO_CALL_RELEASE_GIL_TARGET
         if op.opname == "direct_call":
             funcobj = op.args[0].value._obj
             assert getattr(funcobj, 'calling_conv', 'c') == 'c', (
@@ -218,9 +223,9 @@
                 assert not NON_VOID_ARGS, ("arguments not supported for "
                                            "loop-invariant function!")
             if getattr(func, "_call_aroundstate_target_", None):
-                call_release_gil_target = func._call_aroundstate_target_
-                call_release_gil_target = llmemory.cast_ptr_to_adr(
-                    call_release_gil_target)
+                tgt_func, tgt_saveerr = func._call_aroundstate_target_
+                tgt_func = llmemory.cast_ptr_to_adr(tgt_func)
+                call_release_gil_target = (tgt_func, tgt_saveerr)
         elif op.opname == 'indirect_call':
             # check that we're not trying to call indirectly some
             # function with the special flags
diff --git a/rpython/jit/codewriter/effectinfo.py b/rpython/jit/codewriter/effectinfo.py
--- a/rpython/jit/codewriter/effectinfo.py
+++ b/rpython/jit/codewriter/effectinfo.py
@@ -98,6 +98,8 @@
         OS_NOT_IN_TRACE,
     ])
 
+    _NO_CALL_RELEASE_GIL_TARGET = (llmemory.NULL, 0)
+
     def __new__(cls, readonly_descrs_fields, readonly_descrs_arrays,
                 readonly_descrs_interiorfields,
                 write_descrs_fields, write_descrs_arrays,
@@ -105,7 +107,7 @@
                 extraeffect=EF_CAN_RAISE,
                 oopspecindex=OS_NONE,
                 can_invalidate=False,
-                call_release_gil_target=llmemory.NULL,
+                call_release_gil_target=_NO_CALL_RELEASE_GIL_TARGET,
                 extradescrs=None):
         key = (frozenset_or_none(readonly_descrs_fields),
                frozenset_or_none(readonly_descrs_arrays),
@@ -116,7 +118,8 @@
                extraeffect,
                oopspecindex,
                can_invalidate)
-        if call_release_gil_target:
+        tgt_func, tgt_saveerr = call_release_gil_target
+        if tgt_func:
             key += (object(),)    # don't care about caching in this case
         if key in cls._cache:
             return cls._cache[key]
@@ -171,7 +174,8 @@
         return self.extraeffect >= self.EF_RANDOM_EFFECTS
 
     def is_call_release_gil(self):
-        return bool(self.call_release_gil_target)
+        tgt_func, tgt_saveerr = self.call_release_gil_target
+        return bool(tgt_func)
 
     def __repr__(self):
         more = ''
@@ -194,7 +198,8 @@
                                  extraeffect=EffectInfo.EF_CAN_RAISE,
                                  oopspecindex=EffectInfo.OS_NONE,
                                  can_invalidate=False,
-                                 call_release_gil_target=llmemory.NULL,
+                                 call_release_gil_target=
+                                     EffectInfo._NO_CALL_RELEASE_GIL_TARGET,
                                  extradescr=None):
     from rpython.translator.backendopt.writeanalyze import top_set
     if effects is top_set or extraeffect == EffectInfo.EF_RANDOM_EFFECTS:
diff --git a/rpython/rlib/clibffi.py b/rpython/rlib/clibffi.py
--- a/rpython/rlib/clibffi.py
+++ b/rpython/rlib/clibffi.py
@@ -330,7 +330,8 @@
 else:
     c_ffi_call_return_type = lltype.Void
 c_ffi_call = external('ffi_call', [FFI_CIFP, rffi.VOIDP, rffi.VOIDP,
-                                   VOIDPP], c_ffi_call_return_type)
+                                   VOIDPP], c_ffi_call_return_type,
+                      save_err=rffi.RFFI_ERR_ALL)
 CALLBACK_TP = rffi.CCallback([FFI_CIFP, rffi.VOIDP, rffi.VOIDPP, rffi.VOIDP],
                              lltype.Void)
 c_ffi_prep_closure = external('ffi_prep_closure', [FFI_CLOSUREP, FFI_CIFP,
diff --git a/rpython/rlib/rsignal.py b/rpython/rlib/rsignal.py
--- a/rpython/rlib/rsignal.py
+++ b/rpython/rlib/rsignal.py
@@ -89,10 +89,12 @@
                                     elidable_function=True)
 c_alarm = external('alarm', [rffi.INT], rffi.INT)
 c_pause = external('pause', [], rffi.INT, releasegil=True)
-c_siginterrupt = external('siginterrupt', [rffi.INT, rffi.INT], rffi.INT)
+c_siginterrupt = external('siginterrupt', [rffi.INT, rffi.INT], rffi.INT,
+                          save_err=rffi.RFFI_SAVE_ERRNO)
 
 if sys.platform != 'win32':
     itimervalP = rffi.CArrayPtr(itimerval)
     c_setitimer = external('setitimer',
-                           [rffi.INT, itimervalP, itimervalP], rffi.INT)
+                           [rffi.INT, itimervalP, itimervalP], rffi.INT,
+                           save_err=rffi.RFFI_SAVE_ERRNO)
     c_getitimer = external('getitimer', [rffi.INT, itimervalP], rffi.INT)
diff --git a/rpython/rtyper/lltypesystem/rffi.py b/rpython/rtyper/lltypesystem/rffi.py
--- a/rpython/rtyper/lltypesystem/rffi.py
+++ b/rpython/rtyper/lltypesystem/rffi.py
@@ -213,7 +213,7 @@
         # CALL_RELEASE_GIL directly to 'funcptr'.  This doesn't work if
         # 'funcptr' might be a C macro, though.
         if macro is None:
-            call_external_function._call_aroundstate_target_ = funcptr
+            call_external_function._call_aroundstate_target_ = funcptr, save_err
         #
         call_external_function = func_with_new_name(call_external_function,
                                                     'ccall_' + name)


More information about the pypy-commit mailing list