Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a80c685

Browse files
authored
disallow runtime shutdown when the Python error indicator is set, as it may lead to unpredictable behavior (#1780)
1 parent ac75e0c commit a80c685

File tree

3 files changed

+24
-0
lines changed

3 files changed

+24
-0
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ and other `PyObject` derived types when called from Python.
3636
details about the cause of the failure
3737
- `clr.AddReference` no longer adds ".dll" implicitly
3838
- `PyIter(PyObject)` constructor replaced with static `PyIter.GetIter(PyObject)` method
39+
- Python runtime can no longer be shut down if the Python error indicator is set, as it would have unpredictable behavior
3940
- BREAKING: Return values from .NET methods that return an interface are now automatically
4041
wrapped in that interface. This is a breaking change for users that rely on being
4142
able to access members that are part of the implementation class, but not the

src/runtime/PythonEngine.cs

+6
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,12 @@ public static void Shutdown()
351351
{
352352
return;
353353
}
354+
if (Exceptions.ErrorOccurred())
355+
{
356+
throw new InvalidOperationException(
357+
"Python error indicator is set",
358+
innerException: PythonException.PeekCurrentOrNull(out _));
359+
}
354360
// If the shutdown handlers trigger a domain unload,
355361
// don't call shutdown again.
356362
AppDomain.CurrentDomain.DomainUnload -= OnDomainUnload;

src/runtime/PythonException.cs

+17
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,23 @@ internal static PythonException FetchCurrentRaw()
7575
=> FetchCurrentOrNullRaw()
7676
?? throw new InvalidOperationException("No exception is set");
7777

78+
internal static Exception? PeekCurrentOrNull(out ExceptionDispatchInfo? dispatchInfo)
79+
{
80+
using var _ = new Py.GILState();
81+
82+
Runtime.PyErr_Fetch(out var type, out var value, out var traceback);
83+
Runtime.PyErr_Restore(
84+
new NewReference(type, canBeNull: true).StealNullable(),
85+
new NewReference(value, canBeNull: true).StealNullable(),
86+
new NewReference(traceback, canBeNull: true).StealNullable());
87+
88+
var err = FetchCurrentOrNull(out dispatchInfo);
89+
90+
Runtime.PyErr_Restore(type.StealNullable(), value.StealNullable(), traceback.StealNullable());
91+
92+
return err;
93+
}
94+
7895
internal static Exception? FetchCurrentOrNull(out ExceptionDispatchInfo? dispatchInfo)
7996
{
8097
dispatchInfo = null;

0 commit comments

Comments
 (0)