Author: Armin Rigo <ar...@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) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit