From 17e58ac70a0a0d4e89e987ffcf34ebe4247db2ab Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 23 Feb 2021 22:56:07 -0800 Subject: [PATCH] allow GIL state debugging; require GILState to be properly disposed https://github.com/pythonnet/pythonnet/issues/1389#issuecomment-784716437 --- src/runtime/pythonengine.cs | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/runtime/pythonengine.cs b/src/runtime/pythonengine.cs index 35ea3f6d2..bdacba4c1 100644 --- a/src/runtime/pythonengine.cs +++ b/src/runtime/pythonengine.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Reflection; using System.Runtime.InteropServices; +using System.Threading; namespace Python.Runtime { @@ -51,6 +52,9 @@ public static bool IsInitialized get { return initialized; } } + /// Set to true to enable GIL debugging assistance. + public static bool DebugGIL { get; set; } = false; + internal static DelegateManager DelegateManager { get @@ -668,7 +672,7 @@ public static GILState GIL() PythonEngine.Initialize(); } - return new GILState(); + return PythonEngine.DebugGIL ? new DebugGILState() : new GILState(); } public static PyScope CreateScope() @@ -693,7 +697,7 @@ internal GILState() state = PythonEngine.AcquireLock(); } - public void Dispose() + public virtual void Dispose() { if (this.isDisposed) return; @@ -704,7 +708,23 @@ public void Dispose() ~GILState() { - Dispose(); + throw new InvalidOperationException("GIL must always be released, and it must be released from the same thread that acquired it."); + } + } + + public class DebugGILState : GILState + { + readonly Thread owner; + internal DebugGILState() : base() + { + this.owner = Thread.CurrentThread; + } + public override void Dispose() + { + if (this.owner != Thread.CurrentThread) + throw new InvalidOperationException("GIL must always be released from the same thread, that acquired it"); + + base.Dispose(); } }