From 8b848b3d7bc0ab10c6b0fe573b519f1c981ff895 Mon Sep 17 00:00:00 2001 From: gpetrou Date: Sat, 26 Dec 2020 07:19:19 +0000 Subject: [PATCH 1/4] Add Interrupt method in PythonEngine --- AUTHORS.md | 5 +- CHANGELOG.md | 4 ++ src/embed_tests/TestInterrupt.cs | 83 ++++++++++++++++++++++++++++++++ src/runtime/pythonengine.cs | 9 ++++ src/runtime/runtime.cs | 3 ++ 5 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 src/embed_tests/TestInterrupt.cs diff --git a/AUTHORS.md b/AUTHORS.md index 167fd496c..6cfa216b1 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -66,10 +66,10 @@ - Ville M. Vainio ([@vivainio](https://github.com/vivainio)) - Virgil Dupras ([@hsoft](https://github.com/hsoft)) - Wenguang Yang ([@yagweb](https://github.com/yagweb)) -- William Sardar ([@williamsardar])(https://github.com/williamsardar) +- William Sardar ([@williamsardar](https://github.com/williamsardar)) - Xavier Dupré ([@sdpython](https://github.com/sdpython)) - Zane Purvis ([@zanedp](https://github.com/zanedp)) -- ([@amos402]https://github.com/amos402) +- ([@amos402](https://github.com/amos402)) - ([@bltribble](https://github.com/bltribble)) - ([@civilx64](https://github.com/civilx64)) - ([@GSPP](https://github.com/GSPP)) @@ -82,3 +82,4 @@ - ([@testrunner123](https://github.com/testrunner123)) - ([@DanBarzilian](https://github.com/DanBarzilian)) - ([@alxnull](https://github.com/alxnull)) +- ([@gpetrou](https://github.com/gpetrou)) diff --git a/CHANGELOG.md b/CHANGELOG.md index 147a716b5..e92adb096 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,11 @@ This document follows the conventions laid out in [Keep a CHANGELOG][]. ### Added - Ability to instantiate new .NET arrays using `Array[T](dim1, dim2, ...)` syntax +<<<<<<< HEAD - Python operator method will call C# operator method for supported binary and unary operators ([#1324][p1324]). +======= +- Add Interrupt method in PythonEngine +>>>>>>> Add Interrupt method in PythonEngine ### Changed - Drop support for Python 2, 3.4, and 3.5 diff --git a/src/embed_tests/TestInterrupt.cs b/src/embed_tests/TestInterrupt.cs new file mode 100644 index 000000000..ae59e1603 --- /dev/null +++ b/src/embed_tests/TestInterrupt.cs @@ -0,0 +1,83 @@ + +using System; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; + +using NUnit.Framework; + +using Python.Runtime; + +namespace Python.EmbeddingTest +{ + public class TestInterrupt + { + private IntPtr _threadState; + + [DllImport("Kernel32", EntryPoint = "GetCurrentThreadId", ExactSpelling = true)] + private static extern uint GetCurrentThreadId(); + + [DllImport("libc", EntryPoint = "pthread_self")] + private static extern IntPtr pthread_selfLinux(); + + [DllImport("pthread", EntryPoint = "pthread_self", CallingConvention = CallingConvention.Cdecl)] + private static extern ulong pthread_selfOSX(); + + [OneTimeSetUp] + public void SetUp() + { + PythonEngine.Initialize(); + _threadState = PythonEngine.BeginAllowThreads(); + } + + [OneTimeTearDown] + public void Dispose() + { + PythonEngine.EndAllowThreads(_threadState); + PythonEngine.Shutdown(); + } + + [Test] + public void InterruptTest() + { + int runSimpleStringReturnValue = int.MinValue; + ulong nativeThreadId = 0; + Task.Factory.StartNew(() => + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + nativeThreadId = GetCurrentThreadId(); + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + nativeThreadId = (ulong)pthread_selfLinux(); + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + nativeThreadId = pthread_selfOSX(); + } + + using (Py.GIL()) + { + runSimpleStringReturnValue = PythonEngine.RunSimpleString(@" +import time + +while True: + time.sleep(0.2)"); + } + }); + + Thread.Sleep(200); + + using (Py.GIL()) + { + int interruptReturnValue = PythonEngine.Interrupt(nativeThreadId); + Assert.AreEqual(1, interruptReturnValue); + } + + Thread.Sleep(300); + + Assert.AreEqual(-1, runSimpleStringReturnValue); + } + } +} diff --git a/src/runtime/pythonengine.cs b/src/runtime/pythonengine.cs index df6cf7101..a2bd4f2fe 100644 --- a/src/runtime/pythonengine.cs +++ b/src/runtime/pythonengine.cs @@ -567,6 +567,15 @@ public static void Exec(string code, IntPtr? globals = null, IntPtr? locals = nu } } + /// + /// Interrupts the execution of a thread. + /// + /// The native thread id. + /// The number of thread states modified; this is normally one, but will be zero if the thread id isn’t found. + public static int Interrupt(ulong nativeThreadId) + { + return Runtime.PyThreadState_SetAsyncExc(nativeThreadId, Exceptions.KeyboardInterrupt); + } /// /// RunString Method. Function has been deprecated and will be removed. diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index 2454c038f..2be472faa 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -2143,6 +2143,9 @@ internal static void Py_CLEAR(ref IntPtr ob) [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int Py_AddPendingCall(IntPtr func, IntPtr arg); + [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] + internal static extern int PyThreadState_SetAsyncExc(ulong id, IntPtr exc); + [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int Py_MakePendingCalls(); From d07cd05e9c738f4f62cf91d4e1fc83283c704730 Mon Sep 17 00:00:00 2001 From: gpetrou Date: Sun, 27 Dec 2020 06:48:52 +0000 Subject: [PATCH 2/4] Add GetNativeThreadID method in PythonEngine and different PyThreadState_SetAsyncExc calls for OS and Python version --- CHANGELOG.md | 4 +++ src/embed_tests/TestInterrupt.cs | 26 ++------------ src/runtime/pythonengine.cs | 60 ++++++++++++++++++++++++++++++-- src/runtime/runtime.cs | 13 +++++-- 4 files changed, 74 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e92adb096..2bbfcb373 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,10 +11,14 @@ This document follows the conventions laid out in [Keep a CHANGELOG][]. - Ability to instantiate new .NET arrays using `Array[T](dim1, dim2, ...)` syntax <<<<<<< HEAD +<<<<<<< HEAD - Python operator method will call C# operator method for supported binary and unary operators ([#1324][p1324]). ======= - Add Interrupt method in PythonEngine >>>>>>> Add Interrupt method in PythonEngine +======= +- Add GetNativeThreadID and Interrupt methods in PythonEngine +>>>>>>> Add GetNativeThreadID method in PythonEngine and different PyThreadState_SetAsyncExc calls for OS and Python version ### Changed - Drop support for Python 2, 3.4, and 3.5 diff --git a/src/embed_tests/TestInterrupt.cs b/src/embed_tests/TestInterrupt.cs index ae59e1603..1aceaf080 100644 --- a/src/embed_tests/TestInterrupt.cs +++ b/src/embed_tests/TestInterrupt.cs @@ -1,6 +1,5 @@ using System; -using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; @@ -14,15 +13,6 @@ public class TestInterrupt { private IntPtr _threadState; - [DllImport("Kernel32", EntryPoint = "GetCurrentThreadId", ExactSpelling = true)] - private static extern uint GetCurrentThreadId(); - - [DllImport("libc", EntryPoint = "pthread_self")] - private static extern IntPtr pthread_selfLinux(); - - [DllImport("pthread", EntryPoint = "pthread_self", CallingConvention = CallingConvention.Cdecl)] - private static extern ulong pthread_selfOSX(); - [OneTimeSetUp] public void SetUp() { @@ -44,21 +34,9 @@ public void InterruptTest() ulong nativeThreadId = 0; Task.Factory.StartNew(() => { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - nativeThreadId = GetCurrentThreadId(); - } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - { - nativeThreadId = (ulong)pthread_selfLinux(); - } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - { - nativeThreadId = pthread_selfOSX(); - } - using (Py.GIL()) { + nativeThreadId = PythonEngine.GetNativeThreadID(); runSimpleStringReturnValue = PythonEngine.RunSimpleString(@" import time @@ -75,7 +53,7 @@ import time Assert.AreEqual(1, interruptReturnValue); } - Thread.Sleep(300); + Thread.Sleep(500); Assert.AreEqual(-1, runSimpleStringReturnValue); } diff --git a/src/runtime/pythonengine.cs b/src/runtime/pythonengine.cs index a2bd4f2fe..50e72ca36 100644 --- a/src/runtime/pythonengine.cs +++ b/src/runtime/pythonengine.cs @@ -12,6 +12,15 @@ namespace Python.Runtime /// public class PythonEngine : IDisposable { + [DllImport("Kernel32", EntryPoint = "GetCurrentThreadId", ExactSpelling = true)] + private static extern uint GetCurrentThreadId(); + + [DllImport("libc", EntryPoint = "pthread_self")] + private static extern IntPtr pthread_selfLinux(); + + [DllImport("pthread", EntryPoint = "pthread_self", CallingConvention = CallingConvention.Cdecl)] + private static extern ulong pthread_selfOSX(); + public static ShutdownMode ShutdownMode { get => Runtime.ShutdownMode; @@ -567,14 +576,59 @@ public static void Exec(string code, IntPtr? globals = null, IntPtr? locals = nu } } + /// + /// Gets the native thread ID. + /// + /// The native thread ID. + public static ulong GetNativeThreadID() + { + if (Runtime.PyVersion >= new Version(3, 8)) + { + dynamic threading = Py.Import("threading"); + return threading.get_native_id(); + } + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return GetCurrentThreadId(); + } + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + return (ulong)pthread_selfLinux(); + } + + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + return pthread_selfOSX(); + } + + return 0; + } + /// /// Interrupts the execution of a thread. /// - /// The native thread id. + /// The native thread ID. /// The number of thread states modified; this is normally one, but will be zero if the thread id isn’t found. - public static int Interrupt(ulong nativeThreadId) + public static int Interrupt(ulong nativeThreadID) { - return Runtime.PyThreadState_SetAsyncExc(nativeThreadId, Exceptions.KeyboardInterrupt); + if (Runtime.PyVersion >= new Version(3, 7)) + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return Runtime.PyThreadState_SetAsyncExc37Windows(nativeThreadID, Exceptions.KeyboardInterrupt); + } + + return Runtime.PyThreadState_SetAsyncExc37NonWindows((UIntPtr)nativeThreadID, Exceptions.KeyboardInterrupt); + } + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return Runtime.PyThreadState_SetAsyncExc36Windows((long)nativeThreadID, Exceptions.KeyboardInterrupt); + } + + return Runtime.PyThreadState_SetAsyncExc36NonWindows((IntPtr)nativeThreadID, Exceptions.KeyboardInterrupt); } /// diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index 2be472faa..e964eeedc 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -2143,8 +2143,17 @@ internal static void Py_CLEAR(ref IntPtr ob) [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int Py_AddPendingCall(IntPtr func, IntPtr arg); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyThreadState_SetAsyncExc(ulong id, IntPtr exc); + [DllImport(_PythonDll, EntryPoint = "PyThreadState_SetAsyncExc", CallingConvention = CallingConvention.Cdecl)] + internal static extern int PyThreadState_SetAsyncExc37Windows(ulong id, IntPtr exc); + + [DllImport(_PythonDll, EntryPoint = "PyThreadState_SetAsyncExc", CallingConvention = CallingConvention.Cdecl)] + internal static extern int PyThreadState_SetAsyncExc36Windows(long id, IntPtr exc); + + [DllImport(_PythonDll, EntryPoint = "PyThreadState_SetAsyncExc", CallingConvention = CallingConvention.Cdecl)] + internal static extern int PyThreadState_SetAsyncExc37NonWindows(UIntPtr id, IntPtr exc); + + [DllImport(_PythonDll, EntryPoint = "PyThreadState_SetAsyncExc", CallingConvention = CallingConvention.Cdecl)] + internal static extern int PyThreadState_SetAsyncExc36NonWindows(IntPtr id, IntPtr exc); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int Py_MakePendingCalls(); From f077caf2d201cba1c0290b8745229fa584599ef5 Mon Sep 17 00:00:00 2001 From: gpetrou Date: Sun, 27 Dec 2020 09:53:29 +0000 Subject: [PATCH 3/4] Use get_ident and LLP64 and LP64 in DllImport names and ulong in public methods and assert nativeThreadID value --- CHANGELOG.md | 7 ----- src/embed_tests/TestInterrupt.cs | 10 ++++--- src/runtime/pythonengine.cs | 47 +++----------------------------- src/runtime/runtime.cs | 10 ++----- 4 files changed, 12 insertions(+), 62 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2bbfcb373..9774cdc15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,15 +10,8 @@ This document follows the conventions laid out in [Keep a CHANGELOG][]. ### Added - Ability to instantiate new .NET arrays using `Array[T](dim1, dim2, ...)` syntax -<<<<<<< HEAD -<<<<<<< HEAD - Python operator method will call C# operator method for supported binary and unary operators ([#1324][p1324]). -======= -- Add Interrupt method in PythonEngine ->>>>>>> Add Interrupt method in PythonEngine -======= - Add GetNativeThreadID and Interrupt methods in PythonEngine ->>>>>>> Add GetNativeThreadID method in PythonEngine and different PyThreadState_SetAsyncExc calls for OS and Python version ### Changed - Drop support for Python 2, 3.4, and 3.5 diff --git a/src/embed_tests/TestInterrupt.cs b/src/embed_tests/TestInterrupt.cs index 1aceaf080..1ec7d374d 100644 --- a/src/embed_tests/TestInterrupt.cs +++ b/src/embed_tests/TestInterrupt.cs @@ -31,12 +31,12 @@ public void Dispose() public void InterruptTest() { int runSimpleStringReturnValue = int.MinValue; - ulong nativeThreadId = 0; + ulong nativeThreadID = ulong.MinValue; Task.Factory.StartNew(() => { using (Py.GIL()) { - nativeThreadId = PythonEngine.GetNativeThreadID(); + nativeThreadID = PythonEngine.GetNativeThreadID(); runSimpleStringReturnValue = PythonEngine.RunSimpleString(@" import time @@ -47,13 +47,15 @@ import time Thread.Sleep(200); + Assert.AreNotEqual(ulong.MinValue, nativeThreadID); + using (Py.GIL()) { - int interruptReturnValue = PythonEngine.Interrupt(nativeThreadId); + int interruptReturnValue = PythonEngine.Interrupt(nativeThreadID); Assert.AreEqual(1, interruptReturnValue); } - Thread.Sleep(500); + Thread.Sleep(300); Assert.AreEqual(-1, runSimpleStringReturnValue); } diff --git a/src/runtime/pythonengine.cs b/src/runtime/pythonengine.cs index 50e72ca36..ad2f9a084 100644 --- a/src/runtime/pythonengine.cs +++ b/src/runtime/pythonengine.cs @@ -12,15 +12,6 @@ namespace Python.Runtime /// public class PythonEngine : IDisposable { - [DllImport("Kernel32", EntryPoint = "GetCurrentThreadId", ExactSpelling = true)] - private static extern uint GetCurrentThreadId(); - - [DllImport("libc", EntryPoint = "pthread_self")] - private static extern IntPtr pthread_selfLinux(); - - [DllImport("pthread", EntryPoint = "pthread_self", CallingConvention = CallingConvention.Cdecl)] - private static extern ulong pthread_selfOSX(); - public static ShutdownMode ShutdownMode { get => Runtime.ShutdownMode; @@ -582,28 +573,8 @@ public static void Exec(string code, IntPtr? globals = null, IntPtr? locals = nu /// The native thread ID. public static ulong GetNativeThreadID() { - if (Runtime.PyVersion >= new Version(3, 8)) - { - dynamic threading = Py.Import("threading"); - return threading.get_native_id(); - } - - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - return GetCurrentThreadId(); - } - - if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - { - return (ulong)pthread_selfLinux(); - } - - if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - { - return pthread_selfOSX(); - } - - return 0; + dynamic threading = Py.Import("threading"); + return threading.get_ident(); } /// @@ -613,22 +584,12 @@ public static ulong GetNativeThreadID() /// The number of thread states modified; this is normally one, but will be zero if the thread id isn’t found. public static int Interrupt(ulong nativeThreadID) { - if (Runtime.PyVersion >= new Version(3, 7)) - { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - return Runtime.PyThreadState_SetAsyncExc37Windows(nativeThreadID, Exceptions.KeyboardInterrupt); - } - - return Runtime.PyThreadState_SetAsyncExc37NonWindows((UIntPtr)nativeThreadID, Exceptions.KeyboardInterrupt); - } - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { - return Runtime.PyThreadState_SetAsyncExc36Windows((long)nativeThreadID, Exceptions.KeyboardInterrupt); + return Runtime.PyThreadState_SetAsyncExcLLP64((uint)nativeThreadID, Exceptions.KeyboardInterrupt); } - return Runtime.PyThreadState_SetAsyncExc36NonWindows((IntPtr)nativeThreadID, Exceptions.KeyboardInterrupt); + return Runtime.PyThreadState_SetAsyncExcLP64(nativeThreadID, Exceptions.KeyboardInterrupt); } /// diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index e964eeedc..8197f027b 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -2144,16 +2144,10 @@ internal static void Py_CLEAR(ref IntPtr ob) internal static extern int Py_AddPendingCall(IntPtr func, IntPtr arg); [DllImport(_PythonDll, EntryPoint = "PyThreadState_SetAsyncExc", CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyThreadState_SetAsyncExc37Windows(ulong id, IntPtr exc); + internal static extern int PyThreadState_SetAsyncExcLLP64(uint id, IntPtr exc); [DllImport(_PythonDll, EntryPoint = "PyThreadState_SetAsyncExc", CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyThreadState_SetAsyncExc36Windows(long id, IntPtr exc); - - [DllImport(_PythonDll, EntryPoint = "PyThreadState_SetAsyncExc", CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyThreadState_SetAsyncExc37NonWindows(UIntPtr id, IntPtr exc); - - [DllImport(_PythonDll, EntryPoint = "PyThreadState_SetAsyncExc", CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyThreadState_SetAsyncExc36NonWindows(IntPtr id, IntPtr exc); + internal static extern int PyThreadState_SetAsyncExcLP64(ulong id, IntPtr exc); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int Py_MakePendingCalls(); From 8e7b7c6d024ff710427987debae8dce8e595f2ae Mon Sep 17 00:00:00 2001 From: gpetrou Date: Thu, 21 Jan 2021 07:42:25 +0000 Subject: [PATCH 4/4] Rename to GetPythonThreadID --- CHANGELOG.md | 2 +- src/embed_tests/TestInterrupt.cs | 8 ++++---- src/runtime/pythonengine.cs | 16 ++++++++-------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9774cdc15..375071841 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ This document follows the conventions laid out in [Keep a CHANGELOG][]. - Ability to instantiate new .NET arrays using `Array[T](dim1, dim2, ...)` syntax - Python operator method will call C# operator method for supported binary and unary operators ([#1324][p1324]). -- Add GetNativeThreadID and Interrupt methods in PythonEngine +- Add GetPythonThreadID and Interrupt methods in PythonEngine ### Changed - Drop support for Python 2, 3.4, and 3.5 diff --git a/src/embed_tests/TestInterrupt.cs b/src/embed_tests/TestInterrupt.cs index 1ec7d374d..e075d1194 100644 --- a/src/embed_tests/TestInterrupt.cs +++ b/src/embed_tests/TestInterrupt.cs @@ -31,12 +31,12 @@ public void Dispose() public void InterruptTest() { int runSimpleStringReturnValue = int.MinValue; - ulong nativeThreadID = ulong.MinValue; + ulong pythonThreadID = ulong.MinValue; Task.Factory.StartNew(() => { using (Py.GIL()) { - nativeThreadID = PythonEngine.GetNativeThreadID(); + pythonThreadID = PythonEngine.GetPythonThreadID(); runSimpleStringReturnValue = PythonEngine.RunSimpleString(@" import time @@ -47,11 +47,11 @@ import time Thread.Sleep(200); - Assert.AreNotEqual(ulong.MinValue, nativeThreadID); + Assert.AreNotEqual(ulong.MinValue, pythonThreadID); using (Py.GIL()) { - int interruptReturnValue = PythonEngine.Interrupt(nativeThreadID); + int interruptReturnValue = PythonEngine.Interrupt(pythonThreadID); Assert.AreEqual(1, interruptReturnValue); } diff --git a/src/runtime/pythonengine.cs b/src/runtime/pythonengine.cs index ad2f9a084..781d345e7 100644 --- a/src/runtime/pythonengine.cs +++ b/src/runtime/pythonengine.cs @@ -568,28 +568,28 @@ public static void Exec(string code, IntPtr? globals = null, IntPtr? locals = nu } /// - /// Gets the native thread ID. + /// Gets the Python thread ID. /// - /// The native thread ID. - public static ulong GetNativeThreadID() + /// The Python thread ID. + public static ulong GetPythonThreadID() { dynamic threading = Py.Import("threading"); - return threading.get_ident(); + return threading.InvokeMethod("get_ident"); } /// /// Interrupts the execution of a thread. /// - /// The native thread ID. + /// The Python thread ID. /// The number of thread states modified; this is normally one, but will be zero if the thread id isn’t found. - public static int Interrupt(ulong nativeThreadID) + public static int Interrupt(ulong pythonThreadID) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { - return Runtime.PyThreadState_SetAsyncExcLLP64((uint)nativeThreadID, Exceptions.KeyboardInterrupt); + return Runtime.PyThreadState_SetAsyncExcLLP64((uint)pythonThreadID, Exceptions.KeyboardInterrupt); } - return Runtime.PyThreadState_SetAsyncExcLP64(nativeThreadID, Exceptions.KeyboardInterrupt); + return Runtime.PyThreadState_SetAsyncExcLP64(pythonThreadID, Exceptions.KeyboardInterrupt); } ///