Author: Armin Rigo <ar...@tunes.org> Branch: errno-again Changeset: r75382:80dbb6ecf211 Date: 2015-01-16 12:58 +0100 http://bitbucket.org/pypy/pypy/changeset/80dbb6ecf211/
Log: start work on supporting GetLastError/SetLastError diff --git a/rpython/jit/backend/llsupport/llerrno.py b/rpython/jit/backend/llsupport/llerrno.py --- a/rpython/jit/backend/llsupport/llerrno.py +++ b/rpython/jit/backend/llsupport/llerrno.py @@ -17,6 +17,22 @@ else: return 3 * WORD + +def get_debug_saved_lasterror(cpu): + return cpu._debug_errno_container[4] + +def set_debug_saved_lasterror(cpu, nerrno): + assert nerrno >= 0 + cpu._debug_errno_container[4] = nerrno + +def get_rpy_lasterror_offset(cpu): + if cpu.translate_support_code: + from rpython.rlib import rthread + return rthread.tlfield_rpy_lasterror.getoffset() + else: + return 4 * WORD + + def _fetch_addr_errno(): eci = ExternalCompilationInfo( separate_module_sources=[''' diff --git a/rpython/jit/backend/test/runner_test.py b/rpython/jit/backend/test/runner_test.py --- a/rpython/jit/backend/test/runner_test.py +++ b/rpython/jit/backend/test/runner_test.py @@ -3026,10 +3026,113 @@ assert result == 0 + 345678900 def test_call_release_gil_save_lasterror(self): - XXX + from rpython.translator.tool.cbuild import ExternalCompilationInfo + from rpython.rlib.libffi import types + from rpython.jit.backend.llsupport import llerrno + # + if not isinstance(self.cpu, AbstractLLCPU): + py.test.skip("not on LLGraph") + if sys.platform != 'win32': + py.test.skip("Windows test only") + eci = ExternalCompilationInfo( + separate_module_sources=[''' + #include <windows.h> + RPY_EXPORTED + long __stdcall test_call_release_gil_save_lasterror( + long a, long b, long c, long d, long e, long f, long g) { + SetLastError(42); + return (a + 10*b + 100*c + 1000*d + + 10000*e + 100000*f + 1000000*g); + } + ''']) + fn_name = 'test_call_release_gil_save_lasterror' + func1_ptr = rffi.llexternal(fn_name, [lltype.Signed]*7, lltype.Signed, + compilation_info=eci, _nowrapper=True) + func1_adr = rffi.cast(lltype.Signed, func1_ptr) + calldescr = self.cpu._calldescr_dynamic_for_tests([types.slong]*7, + types.slong) + # + for saveerr in [rffi.RFFI_SAVE_ERRNO, # but not _LASTERROR + rffi.RFFI_SAVE_LASTERROR]: + faildescr = BasicFailDescr(1) + inputargs = [BoxInt() for i in range(7)] + i1 = BoxInt() + ops = [ + ResOperation(rop.CALL_RELEASE_GIL, + [ConstInt(saveerr), ConstInt(func1_adr)] + + inputargs, i1, + descr=calldescr), + ResOperation(rop.GUARD_NOT_FORCED, [], None, descr=faildescr), + ResOperation(rop.FINISH, [i1], None, descr=BasicFinalDescr(0)) + ] + ops[-2].setfailargs([]) + looptoken = JitCellToken() + self.cpu.compile_loop(inputargs, ops, looptoken) + # + llerrno.set_debug_saved_lasterror(self.cpu, 24) + deadframe = self.cpu.execute_token(looptoken, 9, 8, 7, 6, 5, 4, 3) + original_result = self.cpu.get_int_value(deadframe, 0) + result = llerrno.get_debug_saved_lasterror(self.cpu) + print 'saveerr =', saveerr, ': got result =', result + # + if saveerr == rffi.RFFI_SAVE_LASTERROR: + assert result == 42 # from the C code + else: + assert result == 24 # not touched + assert original_result == 3456789 def test_call_release_gil_readsaved_lasterror(self): - XXX + from rpython.translator.tool.cbuild import ExternalCompilationInfo + from rpython.rlib.libffi import types + from rpython.jit.backend.llsupport import llerrno + # + if not isinstance(self.cpu, AbstractLLCPU): + py.test.skip("not on LLGraph") + if sys.platform != 'win32': + py.test.skip("Windows test only") + eci = ExternalCompilationInfo( + separate_module_sources=[r''' + #include <stdio.h> + #include <errno.h> + RPY_EXPORTED + long __stdcall test_call_release_gil_readsaved_lasterror( + long a, long b, long c, long d, long e, long f, long g) { + long r = GetLastError(); + printf("GetLastError() result: %ld\n", r); + r += 100 * (a + 10*b + 100*c + 1000*d + + 10000*e + 100000*f + 1000000*g); + return r; + } + ''']) + fn_name = 'test_call_release_gil_readsaved_lasterror' + func1_ptr = rffi.llexternal(fn_name, [lltype.Signed]*7, lltype.Signed, + compilation_info=eci, _nowrapper=True) + func1_adr = rffi.cast(lltype.Signed, func1_ptr) + calldescr = self.cpu._calldescr_dynamic_for_tests([types.slong]*7, + types.slong) + # + for saveerr in [rffi.RFFI_READSAVED_LASTERROR]: + faildescr = BasicFailDescr(1) + inputargs = [BoxInt() for i in range(7)] + i1 = BoxInt() + ops = [ + ResOperation(rop.CALL_RELEASE_GIL, + [ConstInt(saveerr), ConstInt(func1_adr)] + + inputargs, i1, + descr=calldescr), + ResOperation(rop.GUARD_NOT_FORCED, [], None, descr=faildescr), + ResOperation(rop.FINISH, [i1], None, descr=BasicFinalDescr(0)) + ] + ops[-2].setfailargs([]) + looptoken = JitCellToken() + self.cpu.compile_loop(inputargs, ops, looptoken) + # + llerrno.set_debug_saved_lasterror(self.cpu, 24) + deadframe = self.cpu.execute_token(looptoken, 9, 8, 7, 6, 5, 4, 3) + result = self.cpu.get_int_value(deadframe, 0) + assert llerrno.get_debug_saved_lasterror(self.cpu) == 24 + # + assert result == 24 + 345678900 def test_guard_not_invalidated(self): cpu = self.cpu diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py --- a/rpython/rlib/rposix.py +++ b/rpython/rlib/rposix.py @@ -7,6 +7,8 @@ from rpython.rlib import jit from rpython.translator.platform import platform +WIN32 = os.name == "nt" + class CConstantErrno(CConstant): # these accessors are used when calling get_errno() or set_errno() @@ -109,6 +111,9 @@ @specialize.call_location() def _errno_before(save_err): + if WIN32 and (save_err & rffi.RFFI_READSAVED_LASTERROR): + from rpython.rlib import rthread, rwin32 + rwin32._SetLastError(rthread.tlfield_rpy_lasterror.getraw()) if save_err & rffi.RFFI_READSAVED_ERRNO: from rpython.rlib import rthread _set_errno(rthread.tlfield_rpy_errno.getraw()) @@ -120,6 +125,9 @@ if save_err & rffi.RFFI_SAVE_ERRNO: from rpython.rlib import rthread rthread.tlfield_rpy_errno.setraw(_get_errno()) + if WIN32 and (save_err & rffi.RFFI_SAVE_LASTERROR): + from rpython.rlib import rthread, rwin32 + rthread.tlfield_rpy_lasterror.setraw(rwin32._GetLastError()) if os.name == 'nt': diff --git a/rpython/rlib/rwin32.py b/rpython/rlib/rwin32.py --- a/rpython/rlib/rwin32.py +++ b/rpython/rlib/rwin32.py @@ -123,12 +123,6 @@ _SetLastError = winexternal('SetLastError', [DWORD], lltype.Void, _nowrapper=True, sandboxsafe=True) - def GetLastError_real(): - return rffi.cast(lltype.Signed, _GetLastError()) - - def SetLastError_real(err): - _SetLastError(rffi.cast(DWORD, err)) - def GetLastError_saved(): from rpython.rlib import rthread return rffi.cast(lltype.Signed, rthread.tlfield_rpy_lasterror.getraw()) 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 @@ -64,8 +64,8 @@ RFFI_ZERO_ERRNO_BEFORE = 4 # copy the value 0 into real errno before call RFFI_FULL_ERRNO = RFFI_SAVE_ERRNO | RFFI_READSAVED_ERRNO RFFI_FULL_ERRNO_ZERO = RFFI_SAVE_ERRNO | RFFI_ZERO_ERRNO_BEFORE -RFFI_SAVE_LASTERROR = 8 # XXX implement me! -RFFI_READSAVED_LASTERROR = 16 # XXX implement me! +RFFI_SAVE_LASTERROR = 8 # win32: save GetLastError() after the call +RFFI_READSAVED_LASTERROR = 16 # win32: call SetLastError() before the call RFFI_FULL_LASTERROR = RFFI_SAVE_LASTERROR | RFFI_READSAVED_LASTERROR RFFI_ERR_NONE = 0 RFFI_ERR_ALL = RFFI_FULL_ERRNO | RFFI_FULL_LASTERROR _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit