4
4
using System . Linq ;
5
5
using System . Reflection ;
6
6
using System . Runtime . InteropServices ;
7
+ using System . Threading ;
7
8
8
9
namespace Python . Runtime
9
10
{
@@ -51,6 +52,9 @@ public static bool IsInitialized
51
52
get { return initialized ; }
52
53
}
53
54
55
+ /// <summary>Set to <c>true</c> to enable GIL debugging assistance.</summary>
56
+ public static bool DebugGIL { get ; set ; } = false ;
57
+
54
58
internal static DelegateManager DelegateManager
55
59
{
56
60
get
@@ -633,7 +637,7 @@ public static GILState GIL()
633
637
PythonEngine . Initialize ( ) ;
634
638
}
635
639
636
- return new GILState ( ) ;
640
+ return PythonEngine . DebugGIL ? new DebugGILState ( ) : new GILState ( ) ;
637
641
}
638
642
639
643
public static PyScope CreateScope ( )
@@ -658,7 +662,7 @@ internal GILState()
658
662
state = PythonEngine . AcquireLock ( ) ;
659
663
}
660
664
661
- public void Dispose ( )
665
+ public virtual void Dispose ( )
662
666
{
663
667
if ( this . isDisposed ) return ;
664
668
@@ -669,7 +673,23 @@ public void Dispose()
669
673
670
674
~ GILState ( )
671
675
{
672
- Dispose ( ) ;
676
+ throw new InvalidOperationException ( "GIL must always be released, and it must be released from the same thread that acquired it." ) ;
677
+ }
678
+ }
679
+
680
+ public class DebugGILState : GILState
681
+ {
682
+ readonly Thread owner ;
683
+ internal DebugGILState ( ) : base ( )
684
+ {
685
+ this . owner = Thread . CurrentThread ;
686
+ }
687
+ public override void Dispose ( )
688
+ {
689
+ if ( this . owner != Thread . CurrentThread )
690
+ throw new InvalidOperationException ( "GIL must alwa
538D
ys be released from the same thread, that acquired it" ) ;
691
+
692
+ base . Dispose ( ) ;
673
693
}
674
694
}
675
695
0 commit comments