8000 fixed failure in ExceptionEncoded test case caused by ExceptionDispat… · pythonnet/pythonnet@bec8b7d · GitHub
[go: up one dir, main page]

Skip to content

Commit bec8b7d

Browse files
committed
fixed failure in ExceptionEncoded test case caused by ExceptionDispatchInfo masking exception object
1 parent d667998 commit bec8b7d

File tree

4 files changed

+57
-13
lines changed

4 files changed

+57
-13
lines changed

src/runtime/converter.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,8 @@ internal static bool ToManaged(IntPtr value, Type type,
293293
}
294294

295295

296+
internal static bool ToManagedValue(BorrowedReference value, Type obType, out object result, bool setError)
297+
=> ToManagedValue(value.DangerousGetAddress(), obType, out result, setError);
296298
internal static bool ToManagedValue(IntPtr value, Type obType,
297299
out object result, bool setError)
298300
{

src/runtime/exceptions.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@ public static void SetError(IntPtr ob, IntPtr value)
262262
Runtime.PyErr_SetObject(ob, value);
263263
}
264264

265+
internal const string DispatchInfoAttribute = "__dispatch_info__";
265266
/// <summary>
266267
/// SetError Method
267268
/// </summary>
@@ -288,8 +289,9 @@ public static void SetError(Exception e)
288289
IntPtr etype = Runtime.PyObject_GetAttrString(op, "__class__");
289290
#if NETSTANDARD
290291
var exceptionInfo = ExceptionDispatchInfo.Capture(e);
291-
Runtime.XDecref(op);
292-
op = Converter.ToPython(exceptionInfo);
292+
IntPtr pyInfo = Converter.ToPython(exceptionInfo);
293+
Runtime.PyObject_SetAttrString(op, DispatchInfoAttribute, pyInfo);
294+
Runtime.XDecref(pyInfo);
293295
#endif
294296

295297
Runtime.PyErr_SetObject(etype, op);

src/runtime/pythonexception.cs

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -69,14 +69,19 @@ internal static Exception ThrowLastAsClrException()
6969
Runtime.PyErr_Fetch(out var type, out var value, out var traceback);
7070
try
7171
{
72-
var clrObject = ManagedType.GetManagedObject(value) as CLRObject;
7372
#if NETSTANDARD
74-
if (clrObject?.inst is ExceptionDispatchInfo storedException)
73+
if (!value.IsNull())
7574
{
76-
storedException.Throw();
77-
throw storedException.SourceException; // unreachable
75+
var exceptionInfo = TryGetDispatchInfo(value);
76+
if (exceptionInfo != null)
77+
{
78+
exceptionInfo.Throw();
79+
throw exceptionInfo.SourceException; // unreachable
80+
}
7881
}
7982
#endif
83+
84+
var clrObject = ManagedType.GetManagedObject(value) as CLRObject;
8085
if (clrObject?.inst is Exception e)
8186
{
8287
throw e;
@@ -98,6 +103,37 @@ internal static Exception ThrowLastAsClrException()
98103
}
99104
}
100105

106+
#if NETSTANDARD
107+
static ExceptionDispatchInfo TryGetDispatchInfo(BorrowedReference exception)
108+
{
109+
if (exception.IsNull) return null;
110+
111+
var pyInfo = Runtime.PyObject_GetAttrString(exception, Exceptions.DispatchInfoAttribute);
112+
if (pyInfo.IsNull())
113+
{
114+
if (Exceptions.ExceptionMatches(Exceptions.AttributeError))
115+
{
116+
Exceptions.Clear();
117+
}
118+
return null;
119+
}
120+
121+
try
122+
{
123+
if (Converter.ToManagedValue(pyInfo, typeof(ExceptionDispatchInfo), out object result, setError: false))
124+
{
125+
return (ExceptionDispatchInfo)result;
126+
}
127+
128+
return null;
129+
}
130+
finally
131+
{
132+
pyInfo.Dispose();
133+
}
134+
}
135+
#endif
136+
101137
/// <summary>
102138
/// Requires lock to be acquired elsewhere
103139
/// </summary>
@@ -106,19 +142,20 @@ static Exception FromPyErr(BorrowedReference typeHandle, BorrowedReference value
106142
Exception inner = null;
107143
string pythonTypeName = null, msg = "", tracebackText = null;
108144

109-
var clrObject = ManagedType.GetManagedObject(valueHandle) as CLRObject;
110-
if (clrObject?.inst is Exception e)
111-
{
112-
return e;
113-
}
114-
115145
#if NETSTANDARD
116-
if (clrObject?.inst is ExceptionDispatchInfo exceptionDispatchInfo)
146+
var exceptionDispatchInfo = TryGetDispatchInfo(valueHandle);
147+
if (exceptionDispatchInfo != null)
117148
{
118149
return exceptionDispatchInfo.SourceException;
119150
}
120151
#endif
121152

153+
var clrObject = ManagedType.GetManagedObject(valueHandle) as CLRObject;
154+
if (clrObject?.inst is Exception e)
155+
{
156+
return e;
157+
}
158+
122159
var type = PyObject.FromNullableReference(typeHandle);
123160
var value = PyObject.FromNullableReference(valueHandle);
124161
var traceback = PyObject.FromNullableReference(tracebackHandle);

src/runtime/runtime.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -937,7 +937,10 @@ internal static bool PyObject_IsIterable(IntPtr pointer)
937937
internal static extern int PyObject_HasAttrString(IntPtr pointer, string name);
938938

939939
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)]
940+
[Obsolete("Use overload accepting BorrowedReference")]
940941
internal static extern IntPtr PyObject_GetAttrString(IntPtr pointer, string name);
942+
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)]
943+
internal static extern NewReference PyObject_GetAttrString(BorrowedReference pointer, string name);
941944

942945
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)]
943946
internal static extern int PyObject_SetAttrString(IntPtr pointer, string name, IntPtr value);

0 commit comments

Comments
 (0)
0