8000 Fixes to integrate pythonnet into Unity by benoithudson · Pull Request #745 · pythonnet/pythonnet · GitHub
[go: up one dir, main page]

Skip to content

Fixes to integrate pythonnet into Unity #745

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
410ac15
UNI-63112: unit test for the domain reload crash
Sep 14, 2018
c07fff0
UNI-62864: shutdown on domain reload.
Sep 14, 2018
d016b24
Drive-by improve a hashtable to hashset.
Sep 26, 2018
9ae91ba
UNI-63112: implement platform-aware native code for tp_traverse et al
Sep 26, 2018
bb76ff3
Domain reload work: port previous commit to Windows
benoithudson Sep 28, 2018
0c5b78f
Fixed a bogus comment.
benoithudson Sep 28, 2018
9ffb705
Make prettier
benoithudson Sep 28, 2018
2e03eb8
Added author and changelog information.
Sep 28, 2018
156f554
Fix for linux mmap requiring MAP_PRIVATE
benoithudson Oct 2, 2018
84f5087
Doc and typo fixes.
benoithudson Oct 2, 2018
b9f6c2c
Merge branch 'uni-63112-hotreload-crash-test' of https://github.com/U…
benoithudson Oct 2, 2018
e585bdc
Merge pull request #7 from Unity-Technologies/uni-63112-hotreload-cra…
benoithudson Oct 2, 2018
9ab7b13
Disable app domain test case on .NET Standard
Oct 3, 2018
13f8b53
Fix for CI: define NETSTANDARD in src/embed_tests
Oct 3, 2018
c0b52fa
Fix compile error on OSX that came from an upstream merge.
Oct 3, 2018
4096a95
Fix in dotnet code path: find mmap in libc rather than __Internal
Oct 3, 2018
9b74cce
Fix TypeManager test for running on .NET Core under linux/OSX
Oct 3, 2018
5e15b2c
Fix for python3 tests crashing: it's about test order
Oct 4, 2018
211155e
WIP - debug: turn off "quiet" so that I get an error message
Oct 11, 2018
14bc2e2
Use msbuild v14 for linux/darwin.
Oct 11, 2018
8a80fd5
Upgrade setuptools on appveyor
Oct 11, 2018
dd77fa5
Flush the console on every WriteLine so messages are in order.
Oct 11, 2018
f947e3b
Grasping at straws: try using conda to set up environment
Oct 11, 2018
1fda82b
Revert "Grasping at straws: try using conda to set up environment"
Oct 11, 2018
ec6f6c5
Give up on python 3.4 for appveyor.
Oct 11, 2018
4bac40e
Travis: don't print from domain-reload test
Oct 11, 2018
386a034
Fixed appveyor "allow_failures" syntax.
Oct 11, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
UNI-63112: implement platform-aware native code for tp_traverse et al
1. Implement tp_traverse, tp_clear, and tp_is_gc in native code in memory that
   is *not* released upon domain reload.

   Effect: fixes the crash on domain reload.
   Side effect: leaks a page every domain reload.

2. Use python's platform package to determine what we're running on, so we can
   use the right mmap/mprotect or VirtualAlloc/VirtualProtect routines, the
   right flags for mmap, and (theoretically) the right native code.

   It should be easy to add another system, as long as it has the same kinds of
   functionality.

3. Enable the domain reload test. Added some unit tests for the new stuff.

4. Remove tp_traverse, tp_clear, and tp_is_gc where it was implemented.

Note: I haven't actually tested on windows and linux yet, I'm checking in so I
can do that easily.
  • Loading branch information
Benoit Hudson committed Sep 26, 2018
commit 9ae91baa163a1c8ce4f78d2fcb6b45bd969f2386
1 change: 1 addition & 0 deletions src/embed_tests/Python.EmbeddingTest.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@
<Compile Include="TestPyWith.cs" />
<Compile Include="TestRuntime.cs" />
<Compile Include="TestPyScope.cs" />
<Compile Include="TestTypeManager.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\runtime\Python.Runtime.csproj">
Expand Down
1 change: 0 additions & 1 deletion src/embed_tests/TestDomainReload.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ class TestDomainReload
/// a hot reload).
/// </summary>
[Test]
[Ignore("Test crashes")]
public static void DomainReloadAndGC()
{
// We're set up to run in the directory that includes the bin directory.
Expand Down
19 changes: 19 additions & 0 deletions 8000 src/embed_tests/TestRuntime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,25 @@ namespace Python.EmbeddingTest
{
public class TestRuntime
{
/// <summary>
/// Test the cache of the information from the platform module.
///
/// Test fails on platforms we haven't implemented yet.
/// </summary>
[Test]
public static void PlatformCache()
{
Runtime.Runtime.Initialize();

Assert.That(Runtime.Runtime.Machine, Is.Not.EqualTo(Runtime.Runtime.MachineType.Other));
Assert.That(!string.IsNullOrEmpty(Runtime.Runtime.MachineName));

Assert.That(Runtime.Runtime.OperatingSystem, Is.Not.EqualTo(Runtime.Runtime.OperatingSystemType.Other));
Assert.That(!string.IsNullOrEmpty(Runtime.Runtime.OperatingSystemName));

Runtime.Runtime.Shutdown();
}

[Test]
public static void Py_IsInitializedValue()
{
Expand Down
45 changes: 45 additions & 0 deletions src/embed_tests/TestTypeManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using NUnit.Framework;
using Python.Runtime;
using System.Runtime.InteropServices;

namespace Python.EmbeddingTest
{
class TestTypeManager
{
[Test]
public static void TestNativeCode()
{
Runtime.Runtime.Initialize();

Assert.That(() => { var _ = TypeManager.NativeCode.Active; }, Throws.Nothing);
Assert.That(TypeManager.NativeCode.Active.Code.Length, Is.GreaterThan(0));

Runtime.Runtime.Shutdown();
}

[Test]
public static void TestMemoryMapping()
{
Runtime.Runtime.Initialize();

Assert.That(() => { var _ = TypeManager.CreateMemoryMapper(); }, Throws.Nothing);
var mapper = TypeManager.CreateMemoryMapper();

// Allocate a read-write page.
int len = 12;
var page = mapper.MapWriteable(len);
Assert.That(() => { Marshal.WriteInt64(page, 17); }, Throws.Nothing);
Assert.That(Marshal.ReadInt64(page), Is.EqualTo(17));

// Mark it read-execute, now we can't write anymore (I'm not testing we can execute).
// We should be getting AccessViolationException, but Mono translates
// SIGSEGV to NullReferenceException instead, so just check for some exception.
mapper.SetReadExec(page, len);
Assert.That(Marshal.ReadInt64(page), Is.EqualTo(17));
Assert.That(() => { Marshal.WriteInt64(page, 18); }, Throws.Exception);
Assert.That(Marshal.ReadInt64(page), Is.EqualTo(17));

Runtime.Runtime.Shutdown();
}
}
}
18 changes: 0 additions & 18 deletions src/runtime/classbase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -247,24 +247,6 @@ public static IntPtr tp_str(IntPtr ob)
}


/// <summary>
/// Default implementations for required Python GC support.
/// </summary>
public static int tp_traverse(IntPtr ob, IntPtr func, IntPtr args)
{
return 0;
}

public static int tp_clear(IntPtr ob)
{
return 0;
}

public static int tp_is_gc(IntPtr type)
{
return 1;
}

/// <summary>
/// Standard dealloc implementation for instances of reflected types.
/// </summary>
Expand Down
21 changes: 0 additions & 21 deletions src/runtime/extensiontype.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,27 +81,6 @@ public static int tp_descr_set(IntPtr ds, IntPtr ob, IntPtr val)
}


/// <summary>
/// Required Python GC support.
/// </summary>
public static int tp_traverse(IntPtr ob, IntPtr func, IntPtr args)
{
return 0;
}


public static int tp_clear(IntPtr ob)
{
return 0;
}


public static int tp_is_gc(IntPtr type)
{
return 1;
}


/// <summary>
/// Default dealloc implementation.
/// </summary>
Expand Down
103 changes: 103 additions & 0 deletions src/runtime/runtime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
using System.Collections.Generic;

namespace Python.Runtime
{
Expand Down Expand Up @@ -195,6 +196,57 @@ public class Runtime
// .NET core: System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
internal static bool IsWindows = Environment.OSVersion.Platform == PlatformID.Win32NT;

/// <summary>
/// Operating system type as reported by Python.
/// </summary>
public enum OperatingSystemType
{
Windows,
Darwin,
Linux,
Other
}

static readonly Dictionary<string, OperatingSystemType> OperatingSystemTypeMapping = new Dictionary<string, OperatingSystemType>()
{
{ "Windows", OperatingSystemType.Windows },
{ "Darwin", OperatingSystemType.Darwin },
{ "Linux", OperatingSystemType.Linux },
};

/// <summary>
/// Gets the operating system as reported by python's platform.system().
/// </summary>
public static OperatingSystemType OperatingSystem { get; private set; }

/// <summary>
/// Gets the operating system as reported by python's platform.system().
/// </summary>
public static string OperatingSystemName { get; private set; }

public enum MachineType
{
i386,
x86_64,
Other
};

static readonly Dictionary<string, MachineType> MachineTypeMapping = new Dictionary<string, MachineType>()
{
{ "i386", MachineType.i386 },
{ "x86_64", MachineType.x86_64 },
};

/// <summary>
/// Gets the machine architecture as reported by python's platform.machine().
/// </summary>
public static MachineType Machine { get; private set; }/* set in Initialize using python's platform.machine */

/// <summary>
/// Gets the machine architecture as reported by python's platform.machine().
/// </summary>
public static string MachineName { get; private set; }

internal static bool IsPython2 = pyversionnumber < 30;
internal static bool IsPython3 = pyversionnumber >= 30;

Expand Down Expand Up @@ -331,6 +383,10 @@ internal static void Initialize()
NativeMethods.FreeLibrary(dllLocal);
}
#endif
// Initialize data about the platform we're running on. We need
// this for the type manager and potentially other details. Must
// happen after caching the python types, above.
InitializePlatformData();

// Initialize modules that depend on the runtime class.
AssemblyManager.Initialize();
Expand All @@ -348,6 +404,53 @@ internal static void Initialize()
AssemblyManager.UpdatePath();
}

/// <summary>
/// Initializes the data about platforms.
///
/// This must be the last step when initializing the runtime:
/// GetManagedString needs to have the cached values for types.
/// But it must run before initializing anything outside the runtime
/// because those rely on the platform data.
/// </summary>
private static void InitializePlatformData()
{
IntPtr op;
IntPtr fn;
IntPtr platformModule = PyImport_ImportModule("platform");
IntPtr emptyTuple = PyTuple_New(0);

fn = PyObject_GetAttrString(platformModule, "system");
op = PyObject_Call(fn, emptyTuple, IntPtr.Zero);
OperatingSystemName = GetManagedString(op);
XDecref(op);
XDecref(fn);

fn = PyObject_GetAttrString(platformModule, "machine");
op = PyObject_Call(fn, emptyTuple, IntPtr.Zero);
MachineName = GetManagedString(op);
XDecref(op);
XDecref(fn);

XDecref(emptyTuple);
XDecref(platformModule);

// Now convert the strings into enum values so we can do switch
// statements rather than constant parsing.
OperatingSystemType OSType;
if (!OperatingSystemTypeMapping.TryGetValue(OperatingSystemName, out OSType))
{
OSType = OperatingSystemType.Other;
}
OperatingSystem = OSType;

MachineType MType;
if (!MachineTypeMapping.TryGetValue(MachineName, out MType))
{
MType = MachineType.Other;
}
Machine = MType;
}

internal static void Shutdown()
{
AssemblyManager.Shutdown();
Expand Down
Loading
0