Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

What should reload reload? #1268

Closed
Closed
@benoithudson

Description

@benoithudson

Background:
Amos created the soft reload branch which is now merged to master. It's a large amount of work.

We found#1250 as an issue in that code. Now the question is: disable some functionality or fix it?

The setting is as follows: I have code in Python. It stores references to objects in C#. That means there are proxies in Python pointing to objects in C#.

When C# unloads the domain, those proxies are now pointing to garbage. In the setting where this happens (Unity domain reload), C# will soon load a new domain. The new domain will be a lot like the old one.

Amos implemented a mechanism inruntime_data.cs to reconnect the proxies. The idea is we know all the proxies that were ever build (and not yet deleted). Serialize that C# data usingSystem.Runtime.Serialization. When the new domain arrives, deserialize.

Problem:
Deserialization may fail. See#1250 for one example.

This happens in practice when the Unity user renames a field, a class, a namespace, or an assembly -- and on the Python side we had a reference to one of those. E.g. if we handed a C# static function to a python function that expects a callable, we'd have a FieldObject proxy in the code. If the user renames or deletes the C# static function in their code, when Unity reloads the domain, that FieldObject won't be able to reload.

This will cause an exception when trying to reinitialize Python for .NET on the C# side, and therefore the system is now in an undefined state.

TheSystem.Runtime.Serialization is not fault tolerant. It's not possible to provide a callback if deserialization fails for a certain object. If you control a class you can specify custom deserialization (and serialization) for that class, and you can specifically code your stuff to be fault tolerant, but if you recursively serialize any other classes, upon deserialization everything that got serialized gets deserialized as a flat list; any unhandled exceptions there will stop the deserialization.

What are the user requirements anyway?

For a Unity user, the requirement is that when I change my C# code and Unity automatically reloads, the Python side doesn't throw a fit no matter how mean I've been to it.

This is mainly two things:

  1. If in Python Iimport MyModule where MyModule is in C# (this includesUnityEngine), I need some way to be able to use that even after a domain reload. Ideally the module reloads itself.
  2. If in Python I somehow store a reference to a proxy to C#, I need that the system is able to survive domain reload: it does not crash and it does not leave the Python for .NET data structures in an unstable state.

Possible solution 1: fix the bugs
In#1250 I prototyped a possible solution. The reason deserialization fails in that case is that FieldObject (inruntime/fieldobject.cs) stores a System.Reflection.FieldInfo. Since it can't find that field after reloading, deserialization throws an exception.

Solution:

  1. Add custom serialization to FieldObject.
  2. Serialize the FieldInfo into its own serialization context and store the byte stream.
  3. When we deserialize the FieldObject, deserialize the FieldInfo from that byte stream.
  4. If that fails, catch the exception and mark the FieldObject invalid. When someone wants to access the FieldInfo in the FieldObject, throw an exception.

Effectively this delays the exception so that we can deserialize everything that works and we delay exceptions until the point of use.

There are 13 subclasses of ManagedType that store a pointer to some other object. We can write custom serializations for all of them.

There probably are some ManagedType subclasses that can't reasonably be reloaded, e.g. CLRObject. Those need to simply not serialize, and then fail gracefully just like the others.

Possible solution 2: disable reconnecting the proxies
An alternate plan that Mohammed brought up: what if we just don't reload at all.

We'd basically just add aDisableProxy() function to ManagedType. Most functions on every ManagedType would need to check if the ManagedType is disabled, and if so raise an exception on use. Probably keep ToString working, definitely keep the finalizer/Dispose working.

Possible solution 3: hybrid
Figure out the most important things to reload, and reload those. Probably this is modules (namespaces) and assemblies.

For everything else, disable the proxy.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions


      [8]ページ先頭

      ©2009-2025 Movatter.jp