Author: Pauli Virtanen <[email protected]>
Branch: cpyext-tls-operror
Changeset: r94471:925ca6fe70e4
Date: 2018-03-11 17:56 +0100
http://bitbucket.org/pypy/pypy/changeset/925ca6fe70e4/
Log: cpyext: store error state thread-locally in executioncontext
diff --git a/pypy/module/cpyext/frameobject.py
b/pypy/module/cpyext/frameobject.py
--- a/pypy/module/cpyext/frameobject.py
+++ b/pypy/module/cpyext/frameobject.py
@@ -82,10 +82,10 @@
def PyTraceBack_Here(space, w_frame):
from pypy.interpreter.pytraceback import record_application_traceback
state = space.fromcache(State)
- if state.operror is None:
+ if state.get_exception() is None:
return -1
frame = space.interp_w(PyFrame, w_frame)
- record_application_traceback(space, state.operror, frame, 0)
+ record_application_traceback(space, state.get_exception(), frame, 0)
return 0
@cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)
diff --git a/pypy/module/cpyext/pyerrors.py b/pypy/module/cpyext/pyerrors.py
--- a/pypy/module/cpyext/pyerrors.py
+++ b/pypy/module/cpyext/pyerrors.py
@@ -67,9 +67,10 @@
@cpython_api([], PyObject, result_borrowed=True)
def PyErr_Occurred(space):
state = space.fromcache(State)
- if state.operror is None:
+ operror = state.get_exception()
+ if operror is None:
return None
- return state.operror.w_type # borrowed ref
+ return operror.w_type # borrowed ref
@cpython_api([], lltype.Void)
def PyErr_Clear(space):
diff --git a/pypy/module/cpyext/state.py b/pypy/module/cpyext/state.py
--- a/pypy/module/cpyext/state.py
+++ b/pypy/module/cpyext/state.py
@@ -2,11 +2,18 @@
from rpython.rtyper.lltypesystem import rffi, lltype
from pypy.interpreter.error import OperationError, oefmt
from pypy.interpreter import executioncontext
+from pypy.interpreter.executioncontext import ExecutionContext
from rpython.rtyper.annlowlevel import llhelper
from rpython.rlib.rdynload import DLLHANDLE
from rpython.rlib import rawrefcount
import sys
+
+# Keep track of exceptions raised in cpyext for a particular execution
+# context.
+ExecutionContext.cpyext_operror = None
+
+
class State:
def __init__(self, space):
self.space = space
@@ -18,7 +25,8 @@
def reset(self):
from pypy.module.cpyext.modsupport import PyMethodDef
- self.operror = None
+ ec = self.space.getexecutioncontext()
+ ec.cpyext_operror = None
self.new_method_def = lltype.nullptr(PyMethodDef)
# When importing a package, use this to keep track
@@ -37,17 +45,24 @@
def set_exception(self, operror):
self.clear_exception()
- self.operror = operror
+ ec = self.space.getexecutioncontext()
+ ec.cpyext_operror = operror
def clear_exception(self):
"""Clear the current exception state, and return the operror."""
- operror = self.operror
- self.operror = None
+ ec = self.space.getexecutioncontext()
+ operror = ec.cpyext_operror
+ ec.cpyext_operror = None
return operror
+ def get_exception(self):
+ ec = self.space.getexecutioncontext()
+ return ec.cpyext_operror
+
@specialize.arg(1)
def check_and_raise_exception(self, always=False):
- operror = self.operror
+ ec = self.space.getexecutioncontext()
+ operror = ec.cpyext_operror
if operror:
self.clear_exception()
raise operror
diff --git a/pypy/module/cpyext/test/test_cpyext.py
b/pypy/module/cpyext/test/test_cpyext.py
--- a/pypy/module/cpyext/test/test_cpyext.py
+++ b/pypy/module/cpyext/test/test_cpyext.py
@@ -364,7 +364,7 @@
self.unimport_module(name)
self.cleanup()
state = self.space.fromcache(State)
- assert not state.operror
+ assert state.get_exception() is None
class AppTestCpythonExtension(AppTestCpythonExtensionBase):
diff --git a/pypy/module/cpyext/test/test_pyerrors.py
b/pypy/module/cpyext/test/test_pyerrors.py
--- a/pypy/module/cpyext/test/test_pyerrors.py
+++ b/pypy/module/cpyext/test/test_pyerrors.py
@@ -43,7 +43,8 @@
api.PyErr_SetObject(space.w_ValueError, space.wrap("a value"))
assert api.PyErr_Occurred() is space.w_ValueError
state = space.fromcache(State)
- assert space.eq_w(state.operror.get_w_value(space),
+ operror = state.get_exception()
+ assert space.eq_w(operror.get_w_value(space),
space.wrap("a value"))
api.PyErr_Clear()
@@ -51,12 +52,14 @@
def test_SetNone(self, space, api):
api.PyErr_SetNone(space.w_KeyError)
state = space.fromcache(State)
- assert space.eq_w(state.operror.w_type, space.w_KeyError)
- assert space.eq_w(state.operror.get_w_value(space), space.w_None)
+ operror = state.get_exception()
+ assert space.eq_w(operror.w_type, space.w_KeyError)
+ assert space.eq_w(operror.get_w_value(space), space.w_None)
api.PyErr_Clear()
api.PyErr_NoMemory()
- assert space.eq_w(state.operror.w_type, space.w_MemoryError)
+ operror = state.get_exception()
+ assert space.eq_w(operror.w_type, space.w_MemoryError)
api.PyErr_Clear()
def test_Warning(self, space, api, capfd):
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit