Skip to content

Commit 8fb4704

Browse files
committed
added a workaround for warning in threading module after TestInterrupt
avoid using dynamic in GetPythonThreadID
1 parent 09ecf1b commit 8fb4704

File tree

2 files changed

+49
-14
lines changed

2 files changed

+49
-14
lines changed

src/embed_tests/TestInterrupt.cs

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,51 @@ namespace Python.EmbeddingTest
1111
{
1212
public class TestInterrupt
1313
{
14-
private IntPtr _threadState;
15-
14+
PyObject threading;
1615
[OneTimeSetUp]
1716
public void SetUp()
1817
{
1918
PythonEngine.Initialize();
20-
_threadState = PythonEngine.BeginAllowThreads();
19+
// workaround for assert tlock.locked() warning
20+
threading = Py.Import("threading");
2121
}
2222

2323
[OneTimeTearDown]
2424
public void Dispose()
2525
{
26-
PythonEngine.EndAllowThreads(_threadState);
26+
threading.Dispose();
2727
PythonEngine.Shutdown();
2828
}
2929

30+
[Test]
31+
public void PythonThreadIDStable()
32+
{
33+
long pythonThreadID = 0;
34+
long pythonThreadID2 = 0;
35+
var asyncCall = Task.Factory.StartNew(() =>
36+
{
37+
using (Py.GIL())
38+
{
39+
Interlocked.Exchange(ref pythonThreadID, (long)PythonEngine.GetPythonThreadID());
40+
Interlocked.Exchange(ref pythonThreadID2, (long)PythonEngine.GetPythonThreadID());
41+
}
42+
});
43+
44+
var timeout = Stopwatch.StartNew();
45+
46+
IntPtr threadState = PythonEngine.BeginAllowThreads();
47+
while (Interlocked.Read(ref pythonThreadID) == 0 || Interlocked.Read(ref pythonThreadID2) == 0)
48+
{
49+
Assert.Less(timeout.Elapsed, TimeSpan.FromSeconds(5), "thread IDs were not assigned in time");
50+
}
51+
PythonEngine.EndAllowThreads(threadState);
52+
53+
Assert.IsTrue(asyncCall.Wait(TimeSpan.FromSeconds(5)), "Async thread has not finished in time");
54+
55+
Assert.AreEqual(pythonThreadID, pythonThreadID2);
56+
Assert.NotZero(pythonThreadID);
57+
}
58+
3059
[Test]
3160
public void InterruptTest()
3261
{
@@ -39,26 +68,31 @@ public void InterruptTest()
3968
return PythonEngine.RunSimpleString(@"
4069
import time
4170
42-
while True:
43-
time.sleep(0.2)");
71+
try:
72+
while True:
73+
time.sleep(0.2)
74+
except KeyboardInterrupt:
75+
pass");
4476
}
4577
});
4678

4779
var timeout = Stopwatch.StartNew();
80+
81+
IntPtr threadState = PythonEngine.BeginAllowThreads();
4882
while (Interlocked.Read(ref pythonThreadID) == 0)
4983
{
5084
Assert.Less(timeout.Elapsed, TimeSpan.FromSeconds(5), "thread ID was not assigned in time");
5185
}
86+
PythonEngine.EndAllowThreads(threadState);
5287

53-
using (Py.GIL())
54-
{
55-
int interruptReturnValue = PythonEngine.Interrupt((ulong)Interlocked.Read(ref pythonThreadID));
56-
Assert.AreEqual(1, interruptReturnValue);
57-
}
88+
int interruptReturnValue = PythonEngine.Interrupt((ulong)Interlocked.Read(ref pythonThreadID));
89+
Assert.AreEqual(1, interruptReturnValue);
5890

91+
threadState = PythonEngine.BeginAllowThreads();
5992
Assert.IsTrue(asyncCall.Wait(TimeSpan.FromSeconds(5)), "Async thread was not interrupted in time");
93+
PythonEngine.EndAllowThreads(threadState);
6094

61-
Assert.AreEqual(-1, asyncCall.Result);
95+
Assert.AreEqual(0, asyncCall.Result);
6296
}
6397
}
6498
}

src/runtime/pythonengine.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -570,8 +570,9 @@ internal static void Exec(string code, BorrowedReference globals, BorrowedRefere
570570
/// <returns>The Python thread ID.</returns>
571571
public static ulong GetPythonThreadID()
572572
{
573-
dynamic threading = Py.Import("threading");
574-
return threading.InvokeMethod("get_ident");
573+
using PyObject threading = Py.Import("threading");
574+
using PyObject id = threading.InvokeMethod("get_ident");
575+
return id.As<ulong>();
575576
}
576577

577578
/// <summary>

0 commit comments

Comments
 (0)