Skip to content

Commit 00d19d8

Browse files
committed
added debug information for failures to create a derived type
1 parent 44a36dc commit 00d19d8

File tree

7 files changed

+69
-6
lines changed

7 files changed

+69
-6
lines changed

src/runtime/NewReference.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,27 @@ public IntPtr DangerousMoveToPointerOrNull()
3636
return result;
3737
}
3838

39+
/// <summary>
40+
/// Moves ownership of this reference to a Python C API function,
41+
/// that steals reference passed to it.
42+
/// </summary>
43+
public StolenReference Steal()
44+
{
45+
if (this.IsNull()) throw new NullReferenceException();
46+
47+
return this.StealOrNull();
48+
}
49+
/// <summary>
50+
/// Moves ownership of this reference to a Python C API function,
51+
/// that steals reference passed to it.
52+
/// </summary>
53+
public StolenReference StealOrNull()
54+
{
55+
IntPtr rawPointer = this.pointer;
56+
this.pointer = IntPtr.Zero;
57+
return new StolenReference(rawPointer);
58+
}
59+
3960
/// <summary>
4061
/// Removes this reference to a Python object, and sets it to <c>null</c>.
4162
/// </summary>

src/runtime/StolenReference.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
namespace Python.Runtime
2+
{
3+
using System;
4+
5+
/// <summary>
6+
/// Should only be used for the arguments of Python C API functions, that steal references
7+
/// </summary>
8+
[NonCopyable]
9+
readonly ref struct StolenReference
10+
{
11+
readonly IntPtr pointer;
12+
13+
internal StolenReference(IntPtr pointer)
14+
{
15+
this.pointer = pointer;
16+
}
17+
}
18+
}

src/runtime/exceptions.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Diagnostics;
23
using System.Reflection;
34
using System.Runtime.InteropServices;
45

@@ -374,6 +375,18 @@ internal static IntPtr RaiseTypeError(string message)
374375
return IntPtr.Zero;
375376
}
376377

378+
internal static IntPtr SetCause(Exception cause) {
379+
Runtime.PyErr_Fetch(out NewReference ob, out NewReference val, out NewReference tb);
380+
Debug.Assert(!ob.IsNull() || !val.IsNull());
381+
Runtime.PyErr_NormalizeException(ref ob, ref val, ref tb);
382+
383+
var causePyObj = NewReference.DangerousFromPointer(Converter.ToPython(cause));
384+
Runtime.PyException_SetCause(ob, causePyObj.Steal());
385+
386+
Runtime.PyErr_Restore(ob.Steal(), val.StealOrNull(), tb.StealOrNull());
387+
return IntPtr.Zero;
388+
}
389+
377390
// 2010-11-16: Arranged in python (2.6 & 2.7) source header file order
378391
/* Predefined exceptions are
379392
puplic static variables on the Exceptions class filled in from

src/runtime/finalizer.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ private void DisposeAll()
125125
ValidateRefCount();
126126
#endif
127127
IntPtr obj;
128-
Runtime.PyErr_Fetch(out var errType, out var errVal, out var traceback);
128+
Runtime.PyErr_Fetch(out NewReference errType, out var errVal, out var traceback);
129129

130130
try
131131
{
@@ -160,7 +160,7 @@ private void DisposeAll()
160160
{
161161
// Python requires finalizers to preserve exception:
162162
// https://docs.python.org/3/extending/newtypes.html#finalization-and-de-allocation
163-
Runtime.PyErr_Restore(errType, errVal, traceback);
163+
Runtime.PyErr_Restore(errType.StealOrNull(), errVal.StealOrNull(), traceback.StealOrNull());
164164
}
165165
}
166166
}

src/runtime/pyobject.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ protected virtual void Dispose(bool disposing)
191191

192192
if (refcount == 1)
193193
{
194-
Runtime.PyErr_Fetch(out var errType, out var errVal, out var traceback);
194+
Runtime.PyErr_Fetch(out NewReference errType, out var errVal, out var traceback);
195195

196196
try
197197
{
@@ -202,7 +202,7 @@ protected virtual void Dispose(bool disposing)
202202
{
203203
// Python requires finalizers to preserve exception:
204204
// https://docs.python.org/3/extending/newtypes.html#finalization-and-de-allocation
205-
Runtime.PyErr_Restore(errType, errVal, traceback);
205+
Runtime.PyErr_Restore(errType.StealOrNull(), errVal.StealOrNull(), traceback.StealOrNull());
206206
}
207207
}
208208
else

src/runtime/runtime.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2034,23 +2034,32 @@ internal static IntPtr PyMem_Realloc(IntPtr ptr, long size)
20342034
internal static extern int PyErr_GivenExceptionMatches(IntPtr ob, IntPtr val);
20352035

20362036
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)]
2037-
internal static extern void PyErr_NormalizeException(IntPtr ob, IntPtr val, IntPtr tb);
2037+
internal static extern void PyErr_NormalizeException(ref NewReference ob, ref NewReference val, ref NewReference tb);
20382038

20392039
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)]
20402040
internal static extern IntPtr PyErr_Occurred();
20412041

20422042
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)]
20432043
internal static extern void PyErr_Fetch(out IntPtr ob, out IntPtr val, out IntPtr tb);
2044+
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)]
2045+
internal static extern void PyErr_Fetch(out NewReference ob, out NewReference val, out NewReference tb);
20442046

20452047
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)]
20462048
internal static extern void PyErr_Restore(IntPtr ob, IntPtr val, IntPtr tb);
2049+
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)]
2050+
internal static extern void PyErr_Restore(StolenReference ob, StolenReference val, StolenReference tb);
20472051

20482052
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)]
20492053
internal static extern void PyErr_Clear();
20502054

20512055
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)]
20522056
internal static extern void PyErr_Print();
20532057

2058+
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)]
2059+
internal static extern void PyException_SetCause(BorrowedReference ex, StolenReference cause);
2060+
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)]
2061+
internal static extern int PyException_SetTraceback(BorrowedReference ex, BorrowedReference cause);
2062+
20542063
//====================================================================
20552064
// Cell API
20562065
//====================================================================

src/runtime/typemanager.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,9 @@ internal static IntPtr CreateSubType(IntPtr py_name, IntPtr py_base_type, IntPtr
384384
}
385385
catch (Exception e)
386386
{
387-
return Exceptions.RaiseTypeError(e.Message);
387+
Exceptions.RaiseTypeError("unable to create derived type");
388+
Exceptions.SetCause(e);
389+
return IntPtr.Zero;
388390
}
389391
}
390392

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy