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

Skip to content

Commit d5514fe

Browse files
committed
prevent crash during debugging when attempting to inspect PyObject without GIL
1 parent 2ac5f4e commit d5514fe

File tree

4 files changed

+25
-1
lines changed

4 files changed

+25
-1
lines changed

src/runtime/Util.cs

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ internal static class Util
77
{
88
internal const string UnstableApiMessage =
99
"This API is unstable, and might be changed or removed in the next minor release";
10+
internal const string MinimalPythonVersionRequired =
11+
"Only Python 3.5 or newer is supported";
1012

1113
internal static Int64 ReadCLong(IntPtr tp, int offset)
1214
{

src/runtime/debughelper.cs

+8
Original file line numberDiff line numberDiff line change
@@ -144,5 +144,13 @@ public static void AssertHasReferences(IntPtr obj)
144144
long refcount = Runtime.Refcount(obj);
145145
Debug.Assert(refcount > 0, "Object refcount is 0 or less");
146146
}
147+
148+
[Conditional("DEBUG")]
149+
public static void EnsureGIL()
150+
{
151+
Debug.Assert(HaveInterpreterLock(), "GIL must be acquired");
152+
}
153+
154+
public static bool HaveInterpreterLock() => Runtime.PyGILState_Check() == 1;
147155
}
148156
}

src/runtime/pyobject.cs

+5
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ namespace Python.Runtime
1616
/// for details.
1717
/// </summary>
1818
[Serializable]
19+
[DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")]
1920
public partial class PyObject : DynamicObject, IEnumerable<PyObject>, IDisposable
2021
{
2122
#if TRACE_ALLOC
@@ -1069,6 +1070,10 @@ public override string ToString()
10691070
return result;
10701071
}
10711072

1073+
string DebuggerDisplay => DebugUtil.HaveInterpreterLock()
1074+
? this.ToString()
1075+
: $"pyobj at 0x{this.obj:X} (get Py.GIL to see more info)";
1076+
10721077

10731078
/// <summary>
10741079
/// Equals Method

src/runtime/runtime.cs

+10-1
Original file line numberDiff line numberDiff line change
@@ -832,7 +832,7 @@ internal static unsafe long Refcount(IntPtr op)
832832

833833
internal static IntPtr PyThreadState_Swap(IntPtr key) => Delegates.PyThreadState_Swap(key);
834834

835-
835+
internal static int PyGILState_Check() => Delegates.PyGILState_Check();
836836
internal static IntPtr PyGILState_Ensure() => Delegates.PyGILState_Ensure();
837837

838838

@@ -2302,6 +2302,14 @@ static Delegates()
23022302
PyThread_get_thread_ident = (delegate* unmanaged[Cdecl]<int>)GetFunctionByName(nameof(PyThread_get_thread_ident), GetUnmanagedDll(_PythonDll));
23032303
PyThread_set_key_value = (delegate* unmanaged[Cdecl]<IntPtr, IntPtr, int>)GetFunctionByName(nameof(PyThread_set_key_value), GetUnmanagedDll(_PythonDll));
23042304
PyThreadState_Swap = (delegate* unmanaged[Cdecl]<IntPtr, IntPtr>)GetFunctionByName(nameof(PyThreadState_Swap), GetUnmanagedDll(_PythonDll));
2305+
try
2306+
{
2307+
PyGILState_Check = (delegate* unmanaged[Cdecl]<int>)GetFunctionByName(nameof(PyGILState_Check), GetUnmanagedDll(_PythonDll));
2308+
}
2309+
catch (MissingMethodException e)
2310+
{
2311+
throw new NotSupportedException(Util.MinimalPythonVersionRequired, innerException: e);
2312+
}
23052313
PyGILState_Ensure = (delegate* unmanaged[Cdecl]<IntPtr>)GetFunctionByName(nameof(PyGILState_Ensure), GetUnmanagedDll(_PythonDll));
23062314
PyGILState_Release = (delegate* unmanaged[Cdecl]<IntPtr, void>)GetFunctionByName(nameof(PyGILState_Release), GetUnmanagedDll(_PythonDll));
23072315
PyGILState_GetThisThreadState = (delegate* unmanaged[Cdecl]<IntPtr>)GetFunctionByName(nameof(PyGILState_GetThisThreadState), GetUnmanagedDll(_PythonDll));
@@ -2605,6 +2613,7 @@ static Delegates()
26052613
internal static delegate* unmanaged[Cdecl]<int> PyThread_get_thread_ident { get; }
26062614
internal static delegate* unmanaged[Cdecl]<IntPtr, IntPtr, int> PyThread_set_key_value { get; }
26072615
internal static delegate* unmanaged[Cdecl]<IntPtr, IntPtr> PyThreadState_Swap { get; }
2616+
internal static delegate* unmanaged[Cdecl]<int> PyGILState_Check { get; }
26082617
internal static delegate* unmanaged[Cdecl]<IntPtr> PyGILState_Ensure { get; }
26092618
internal static delegate* unmanaged[Cdecl]<IntPtr, void> PyGILState_Release { get; }
26102619
internal static delegate* unmanaged[Cdecl]<IntPtr> PyGILState_GetThisThreadState { get; }

0 commit comments

Comments
 (0)