ReactiveUI icon indicating copy to clipboard operation
ReactiveUI copied to clipboard

[Bug]: ReactiveUI incompatible with .NET Assembly Load Contexts

Open guillermooo opened this issue 1 year ago • 4 comments

Describe the bug 🐞

It appears that ReactiveUI (RxUI) cannot be used in conjunction with Assembly Load Contexts (ALCs).

Relevant documentation:

Step to reproduce

  • Load ReactiveUI into ALC
  • Unload ALC
  • Reload ALC

Any .WhenAnyValue() subscriptions will generate a TypeLoadException.

Reproduction repository

https://github.com/guillermooo/rxui-alc

Expected behavior

ReactiveUI should support ALCs correctly.

Screenshots 🖼️

No response

IDE

No response

Operating system

Windows

Version

No response

Device

No response

ReactiveUI Version

All

Additional information ℹ️

I haven't been able to find the root of the issue, but I've explored Type caches such as the one used by ReactiveUI.Reflection.ReallyFindType() and lingering references in Splat's registry without much success so far. But I admit I'm not sure what I should be looking for. I have not tried using WinDbg yet, in spite of being the suggested approach by the .NET documentation linked above.

The only lead I could find to date is that the Splat registry does seem to be pristine when the ALC first loads, and polluted after the ALC is reloaded.

If no fix is found, at least determine that RxUI is incompatible with ALCs due to DLL unloadability issues and document the limitation prominently.

guillermooo avatar Oct 03 '23 17:10 guillermooo

Thank you for providing a repo showing the issue you are experiencing, I personally have used this with domain level disposal where all dll's are unloaded to clean up, this was using a older version of RxUI so it's possible that there's now a difference somewhere that is blocking the unloading process. Ensuring that every subscription is fully disposed was a key thing from what I recall, anything left active will block the unloading process and fail.

ChrisPulman avatar Oct 03 '23 18:10 ChrisPulman

@ChrisPulman My understanding is that Application Domains (.NET Framework) forcibly unload assemblies, while ALCs require cooperation to ensure a clean unload. I tried to pare down the repro steps to the absolute minimum and I think disposal of subs is not the issue in the provided repro example. For reference, the rules for ALCs are doumented here.

I think the issue I'm hitting is assembly identity (if that makes any sense), where something in ReactiveUI outlives the ALC and persists after the ALC reload, which doesn't really make much sense to me because then the assembly wasn't unloaded, I suppose, but that's my best explanation at the moment.

guillermooo avatar Oct 03 '23 22:10 guillermooo

I'm evaluating RXUI for a context where there's likely to be some ALC usage in the mix - is there anyone actively looking at this?

I have a fair amount of experience debugging ALC issues - if need be I could take a look under the hood

Texl avatar Aug 07 '24 20:08 Texl

I did take a look and the root of the issue is the static initialisers of ReactiveUI and Splat, as currently we have no way to dispose of the resources spun up at initialisation, they remain alive keeping the ALC from removing them. The ReactiveUI resources are currently only removed upon closure of an application. There could also be something with some of the elements not being disposable that restrict ALC from removing them.

@Texl your more than welcome to take a look, the issue may be a bigger issue than first thought but if you have any ideas on how we may enable this to work it would be much appreciated. Depending on how much of a change would then be involved we can then come up with a fix.

ChrisPulman avatar Aug 08 '24 00:08 ChrisPulman