Skip to content

AssemblyManager.FindAssemblyCandidates runs without GIL and crashes with "Attempted to read or write protected memory" unpredictably #2481

@acidbubbles

Description

@acidbubbles

Environment

  • Pythonnet version: 3.0.4
  • Python version: 3.11.9
  • Operating System: Windows 11 Pro
  • .NET Runtime: .NET Core 8

Details

When assemblies are dynamically loaded in .NET, PythonNet assembly loading hook can crash with "Attempted to read or write protected memory." I'm still trying to make a repro, but maybe you'll immediately see what's wrong.

using var importWarning = Runtime.PyObject_GetAttrString(Exceptions.exceptions_module, "ImportWarning");

I think that the issue may be that during assembly loading, the AssemblyManager hook runs without a GIL, so it may crash with the error above. I've seen multiple stack traces happening at different times, often in code completely unrelated to PythonNet (there is multithreading, I use PythonEngine.BeginAllowThreads())

This did not happen in version 3.0.3.

  • Describe what you were trying to get done.

    Run an application normally that has more than one assembly being loaded (e.g. resources)

  • What commands did you run to trigger this issue? If you can provide a
    Minimal, Complete, and Verifiable example
    this will help us understand the issue.

I will try to provide one, although it's difficult to reproduce reliably

  • If there was a crash, please include the traceback here.
Fatal error. System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
   at Python.Runtime.Runtime.PyObject_GetAttrString(Python.Runtime.BorrowedReference, System.String)
   at Python.Runtime.AssemblyManager+<FindAssemblyCandidates>d__15.MoveNext()
   at System.Linq.Enumerable.TryGetFirst[[System.__Canon, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](System.Collections.Generic.IEnumerable`1<System.__Canon>, Boolean ByRef)
   at System.Linq.Enumerable.FirstOrDefault[[System.__Canon, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](System.Collections.Generic.IEnumerable`1<System.__Canon>)
   at Python.Runtime.AssemblyManager.FindAssembly(System.String)
   at Python.Runtime.AssemblyManager.LoadAssemblyPath(System.String)
   at Python.Runtime.AssemblyManager.ResolveHandler(System.Object, System.ResolveEventArgs)
   at System.Runtime.Loader.AssemblyLoadContext.InvokeResolveEvent(System.ResolveEventHandler, System.Reflection.RuntimeAssembly, System.String)
   at System.Reflection.RuntimeAssembly.InternalLoad(System.Reflection.AssemblyName, System.Threading.StackCrawlMark ByRef, System.Runtime.Loader.AssemblyLoadContext, System.Reflection.RuntimeAssembly, Boolean)
  at ...

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions