Skip to content

Commit e1bf4a3

Browse files
committed
Implement correct exception restoring.
1 parent 90224f6 commit e1bf4a3

File tree

6 files changed

+38
-25
lines changed

6 files changed

+38
-25
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ImpModuleBuiltins.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,8 +191,17 @@ private Object loadDynamicModuleWithSpec(String name, String path, Node readNode
191191
throw raise(ImportError, "no function PyInit_%s found in %s", basename, path);
192192
}
193193
try {
194+
// save current exception state
195+
PException exceptionState = getContext().getCurrentException();
196+
// clear current exception such that native code has clean environment
197+
getContext().setCurrentException(null);
198+
194199
Object nativeResult = ForeignAccess.sendExecute(executeNode, pyinitFunc);
195200
TruffleCextBuiltins.checkFunctionResult(getContext(), isNullNode, "PyInit_" + basename, nativeResult);
201+
202+
// restore previous exception state
203+
getContext().setCurrentException(exceptionState);
204+
196205
Object result = AsPythonObjectNode.doSlowPath(nativeResult);
197206
if (!(result instanceof PythonModule)) {
198207
// PyModuleDef_Init(pyModuleDef)

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TruffleCextBuiltins.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,8 @@ private Object getLongItem(PDict nativeMembers, String key) {
548548
// roughly equivalent to _Py_CheckFunctionResult in Objects/call.c
549549
public static Object checkFunctionResult(PythonContext context, Node isNullNode, String name, Object result) {
550550
PException currentException = context.getCurrentException();
551+
// consume exception
552+
context.setCurrentException(null);
551553
boolean errOccurred = currentException != null;
552554
if (PGuards.isForeignObject(result) && ForeignAccess.sendIsNull(isNullNode, (TruffleObject) result) || result == PNone.NO_VALUE) {
553555
if (!errOccurred) {
@@ -613,7 +615,12 @@ public Object execute(VirtualFrame frame) {
613615
}
614616
// save current exception state
615617
PException exceptionState = getContext().getCurrentException();
618+
// clear current exception such that native code has clean environment
619+
getContext().setCurrentException(null);
620+
616621
Object result = fromNative(asPythonObjectNode.execute(checkFunctionResult(getContext(), isNullNode, name, ForeignAccess.sendExecute(executeNode, fun, arguments))));
622+
623+
// restore previous exception state
617624
getContext().setCurrentException(exceptionState);
618625
return result;
619626
} catch (UnsupportedTypeException | ArityException | UnsupportedMessageException e) {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/GeneratorTryExceptNode.java

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,10 @@ public GeneratorTryExceptNode(PNode body, ExceptNode[] exceptNodes, PNode orelse
6565
public Object execute(VirtualFrame frame) {
6666
Object result = PNone.NONE;
6767

68+
PException exceptionState = getContext().getCurrentException();
69+
6870
if (isActive(frame, exceptFlag)) {
69-
catchException(frame, getActiveException(frame));
71+
catchException(frame, getActiveException(frame), exceptionState);
7072
return doReturn(frame, result);
7173
}
7274

@@ -80,7 +82,7 @@ public Object execute(VirtualFrame frame) {
8082
} catch (PException ex) {
8183
setActive(frame, exceptFlag, true);
8284
setActiveException(frame, ex);
83-
catchException(frame, ex);
85+
catchException(frame, ex, exceptionState);
8486
return doReturn(frame, result);
8587
}
8688

@@ -95,7 +97,7 @@ private Object doReturn(VirtualFrame frame, Object result) {
9597
}
9698

9799
@ExplodeLoop
98-
private void catchException(VirtualFrame frame, PException exception) {
100+
private void catchException(VirtualFrame frame, PException exception, PException exceptionState) {
99101
ExceptNode[] exceptNodes = getExceptNodes();
100102
final int matchingExceptNodeIndex = getIndex(frame, exceptIndex);
101103
boolean wasHandled = false;
@@ -108,7 +110,7 @@ private void catchException(VirtualFrame frame, PException exception) {
108110
ExceptNode exceptNode = exceptNodes[i];
109111
setIndex(frame, exceptIndex, i + 1);
110112
if (exceptNode.matchesException(frame, exception)) {
111-
runExceptionHandler(frame, exception, exceptNode);
113+
runExceptionHandler(frame, exception, exceptNode, exceptionState);
112114
wasHandled = true;
113115
}
114116
}
@@ -117,7 +119,7 @@ private void catchException(VirtualFrame frame, PException exception) {
117119
// we already found the right except handler, jump back into
118120
// it directly
119121
ExceptNode exceptNode = exceptNodes[matchingExceptNodeIndex - 1];
120-
runExceptionHandler(frame, exception, exceptNode);
122+
runExceptionHandler(frame, exception, exceptNode, exceptionState);
121123
wasHandled = true;
122124
}
123125
reset(frame);
@@ -127,11 +129,15 @@ private void catchException(VirtualFrame frame, PException exception) {
127129
}
128130
}
129131

130-
private static void runExceptionHandler(VirtualFrame frame, PException exception, ExceptNode exceptNode) {
132+
private void runExceptionHandler(VirtualFrame frame, PException exception, ExceptNode exceptNode, PException exceptionState) {
131133
try {
132134
exceptNode.executeExcept(frame, exception);
133135
} catch (ExceptionHandledException e) {
134136
return;
137+
} finally {
138+
// restore previous exception state, this won't happen if the except block raises an
139+
// exception
140+
getContext().setCurrentException(exceptionState);
135141
}
136142
}
137143

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/ExceptNode.java

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,7 @@ public void executeExcept(VirtualFrame frame, PException e) {
6464
getCore().setCurrentException(e);
6565
}
6666

67-
try {
68-
body.execute(frame);
69-
} finally {
70-
// clear the exception after executing the except body.
71-
if (context != null) {
72-
context.setCurrentException(null);
73-
}
74-
}
67+
body.execute(frame);
7568
throw ExceptionHandledException.INSTANCE;
7669
}
7770

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/TryExceptNode.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,12 @@ public TryExceptNode(PNode body, ExceptNode[] exceptNodes, PNode orelse) {
6060

6161
@Override
6262
public Object execute(VirtualFrame frame) {
63+
// store current exception state for later restore
64+
PException exceptionState = getContext().getCurrentException();
6365
try {
6466
body.execute(frame);
6567
} catch (PException ex) {
66-
catchException(frame, ex);
68+
catchException(frame, ex, exceptionState);
6769
return PNone.NONE;
6870
} catch (Exception e) {
6971
if (!seenException) {
@@ -78,7 +80,7 @@ public Object execute(VirtualFrame frame) {
7880
PException pe = new PException(getBaseException(e), this);
7981
pe.getExceptionObject().setException(pe);
8082
try {
81-
catchException(frame, pe);
83+
catchException(frame, pe, exceptionState);
8284
} catch (PException pe_thrown) {
8385
if (pe_thrown != pe) {
8486
throw e;
@@ -98,7 +100,7 @@ private PBaseException getBaseException(Exception t) {
98100
}
99101

100102
@ExplodeLoop
101-
private void catchException(VirtualFrame frame, PException exception) {
103+
private void catchException(VirtualFrame frame, PException exception, PException exceptionState) {
102104
boolean wasHandled = false;
103105
for (ExceptNode exceptNode : exceptNodes) {
104106
// we want a constant loop iteration count for ExplodeLoop to work,
@@ -109,6 +111,10 @@ private void catchException(VirtualFrame frame, PException exception) {
109111
exceptNode.executeExcept(frame, exception);
110112
} catch (ExceptionHandledException e) {
111113
wasHandled = true;
114+
} finally {
115+
// restore previous exception state, this won't happen if the except block
116+
// raises an exception
117+
getContext().setCurrentException(exceptionState);
112118
}
113119
}
114120
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/exception/PException.java

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -138,35 +138,27 @@ public boolean isExit() {
138138
return exit;
139139
}
140140

141-
private static void popException(PythonCore core) {
142-
core.getContext().setCurrentException(null);
143-
}
144-
145141
public void expectIndexError(PythonCore core, ConditionProfile profile) {
146142
if (profile.profile(getType() != core.getErrorClass(PythonErrorType.IndexError))) {
147143
throw this;
148144
}
149-
popException(core);
150145
}
151146

152147
public void expectStopIteration(PythonCore core, ConditionProfile profile) {
153148
if (profile.profile(getType() != core.getErrorClass(PythonErrorType.StopIteration))) {
154149
throw this;
155150
}
156-
popException(core);
157151
}
158152

159153
public void expectAttributeError(PythonCore core, ConditionProfile profile) {
160154
if (profile.profile(getType() != core.getErrorClass(PythonErrorType.AttributeError))) {
161155
throw this;
162156
}
163-
popException(core);
164157
}
165158

166159
public void expect(PythonErrorType error, PythonCore core, ConditionProfile profile) {
167160
if (profile.profile(getType() != core.getErrorClass(error))) {
168161
throw this;
169162
}
170-
popException(core);
171163
}
172164
}

0 commit comments

Comments
 (0)