-
Notifications
You must be signed in to change notification settings - Fork 518
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
Random crashes with "Could not find an existing managed instance for this object, nor was it possible to create a new managed instance" #21648
Comments
These issues can be rather difficult to track down, and it's imperative to be able to reproduce them, otherwise we'll just be guessing. However, there's one thing you can do to try to trigger them: run the GC aggressively. Something like this should do it: static void Main (string[] arguments)
{
var thread = new Thread (() => {
while (true) {
Thread.Sleep (5000);
GC.Collect ();
}
});
thread.IsBackground = true;
thread.Start ();
// ...
UIApplication.Main(args, null, typeof(AppDelegate));
} This is obviously not meant to be shipped, but running with this during development will often make the problems you're experiencing easier to reproduce. Can you try this and see if you have any luck? |
Thanks again for your suggestion to aggressively trigger the GC to help reproduce the crashes. Interestingly, we had similar GC.Collect() code in place previously, as part of our attempts to address memory-related issues. This was a temporary, desperate measure to mitigate memory related crashes we were encountering, but it wasn’t a long-term solution. (We also had some temporary teardown code in place, similar to the approach used in the so called "MemoryToolkit". However, that code has since been removed as well.) Since your suggestion, we've removed the GC.Collect() code entirely in our most recent release (as of last week). Unfortunately, we're still seeing random crashes, but the key difference is that we no longer have any log output. This leads us to suspect that iOS might be terminating the app due to memory pressure, rather than an issue directly related to GC. We’re continuing to monitor the situation and try to gather more data. Given that the crashes seem random and aren’t easily reproducible. |
Just to vent a little... The ticket is closed now, and of course, we can’t reopen it after 7 days. We've spent so much time profiling and troubleshooting this issue, dealing with memory management problems that have been around since Xamarin.Forms. It feels like we've been fighting memory leaks for ages, and now we're just left hanging without any way to follow up. Honestly, it's frustrating not being able to continue the conversation or get the support we need. |
I'm sorry to hear about your struggles, and we're here to help. We can always reopen issues, so feel free to open a new issue if you can't reopen an issue yourself, we're happy to do that for you. |
Note that the GC.Collect code shouldn't make a crash app (or fix any crashes [1]) - it's purpose is to trigger any crashes more reliably during development, which would hopefully make them easier to diagnose and fix (instead of hearing about the app crashing for your customers, and not being able to reproduce yourself). [1]: the one exception here is that GC.Collect may keep your app's memory usage lower, thus preventing the OS from terminating the app if it uses a lot of memory. Note that if there are memory leaks, the app will likely crash sooner or later anyway, the GC.Collect will just delay it. |
Thank you for taking the time to respond - I really appreciate it and feel honored, especially since I’ve read many of your responses and blogs over the years. Apologies if my earlier comment came off unconstructive; it’s just been a tough issue to tackle. We’ve been trying to follow best practices as much as possible, like using static event handlers instead of anonymous, implementing INotifyPropertyChanged properly, and keeping object lifetimes in check with DI and so on. That said, I haven’t dived too deeply into profiling snapshots yet - it’s quite complex for me to fully grasp. One thing I’ve been wondering: could this issue stem from how the Mono GC and native iOS GC might be interacting? For instance, is it possible that objects are being collected too early as it doesn't makes much sense to me, iOS (?) tries to instantiate a new managed instance. Or might it work if I tried using custom handlers and try to introduce such constructor myself?! I completely understand how important it is to have a reproduction sample, and I’d genuinely love to provide one. Unfortunately, our corporate app has grown significantly in complexity, and with the ongoing pressure of the project, creating a simplified example hasn’t been feasible. That said, we even brought in freelance “specialists” to help diagnose and address these memory-related challenges, but unfortunately, they weren’t able to offer any better solutions, which has been discouraging. Well, I don’t know... this really sucks as a bug report, to be honest. I’ve probably used enough ChatGPT energy to power a small city for a year just trying to figure out how to frame this properly. Maybe this is turning into more of a discussion than a report at this point? I have to admit, I’m feeling a bit desperate at this point, but I really appreciate all the help and insights you’ve provided so far. I’m truly grateful for any further suggestions you might have that could help me work through this. Thanks again for your time, support, and guidance - it's really appreciated! |
PS: The app's complexity stems from several factors. It includes dozens of pages with intricate logic, and an ERP-like approach that stores form definitions in the database. Each form can contain 200+ controls, adding to the challenge of managing data and rendering. Users can upload multiple photos, resulting in terabytes of data. The app also relies on third-party libraries like Syncfusion. Additionally, background threads are used for tasks like data/image uploads (to sync local "offline" data with the server) and data processing, requiring careful management of thread safety and performance. |
There are a couple of strategies I tend to use when diagnosing this issues:
There are a couple of things you need to know first:
Typically, this is because the GC has determined that the managed instance is no longer needed, and it's been collected. The last important bit to know is that we will automatically keep the managed instance alive, as long as the native instance is. Now the conundrum is: if the native instance showed up in managed code, it's still alive, which means the managed instance shouldn't have been collected... there's at least one caveat to this: if native code only has a weak reference to the native instance, we won't see this weak reference, and we'll think the native instance is no longer alive. Now to the investigation: Typically, people try to answer the question "why is this instance freed/collected by the GC?" - but I like to flip the question to become "why should this instance not be freed/collected by the GC?", and sometimes that yields interesting results. Now I don't know your code base, so I can't offer any more specific advice. Also, you're using MAUI, which often complicates matters. Often this technique doesn't give any results, but combined with the second one I usually figure something out:
So for instance for your second stack trace:
This seems to have happened when the keyboard closed ("KeyboardAutoManagerScroll.WillHideKeyboard" is one of the stack frames). I believe it's possible to open and close the keyboard in code, so I would add that code to the app on a timer (say open and close the keyboard once per second), and then just leave it running for a few hours. Running the GC on a background thread as I previously mentioned would also be a good idea (or you can try both with and without the aggressive GC). A final note: these are crashes in the UI layer of your app. It rarely matters what the app does in the background, or in any UI not shown around the time of the crash. [1]: sometimes the names match exactly, sometimes they don't - this is not important. |
For now I am going to try this as a workaround:
I'll try to reproduce this anyhow and maybe put a "aggressive GC" version on Testflight for our Testers. If I come up with something new I'll open another ticket. Thanks |
Same problem here. Kind of same story too. Though we are still on .NET8 and are using a heavily modified version of the "MemoryToolkit" and regular GCs to prevent leaks. From our crash analytics the crash happens most (all?) of the time when the app is resumed. So may be unloaded gets called when going to sleep, the hander disconnects, managed objects are disposed and this leads to problems on resume. Sleep/resume is somewhat different then a normal page change, so this might be related to it. But as for you, it is difficult to reproduce and happens only very sporadically and only in our newest release. Which means it is either related to some changes we did to our MemoryToolkit (like calling handler.disconnect for some controls) or the update from maui 8.0.92 to 8.0.100. |
Sounds like we’re dealing with pretty much the same issue. And we do use Syncfusion indeed - mostly for SfComboBox and SfListView. Although I have some mixed feelings towards Syncfusion, I am not sure if they're the origin (but cannot exclude it either). When I tested MemoryToolkit like 6 months ago it seemed very promising initially. But the DisconnectHandler thing in particular was problematic and led to crashes (still remember that line), so this was kind of a show stopper for the use of MemoryToolkit (so I removed it). If I remember correctly MemoryToolkit also collected some things too early leading to "white" pages (I stumbled over some code in MAUI repo here, that by default Shell is caching the last page as a performance optimization??) For years we used basically the same approach as MemoryToolkit (try do clear children, nulling BindingContext, try to kill EventHandlers with reflection etc.) but I also removed that code entirely shortly after that because it never had a huge impact on the memory situation and I suspected it of degrading the stability in more recent versions of MAUI (and it was ugly 😄). As a side note: We did not wire our "teardown code" directly to Unload, but invoked it after navigating away from the page (only for pages manually pushed onto the navigation stack). I think the whole "Could not find an existing managed instance for this object" gained momentum after that. Well looking at the timeline, for us it would have been introduced with Microsoft.Maui.Controls 8.0.6x. Thank you for sharing your insights - I hope this helps to narrow down the cause. |
PS: Our testers will start with the "constructor workaround" in January, maybe with go live following soon after. If I don't forget to, I'll share the results here. |
Thanks for the feedback. SfCombox and SfListView are exactly the two controls which we identified having memory issues. I was in contact with syncfusion about our findings and their solution for .NET 8 was to call handler.disconnect in unload. For .NET 9 they told us it will not be necessary because it is called by default (which would explain why you face issues although you do not call handler.disconnect manually). We are still using MemoryToolkit, but a heavily modified version of it, as we also faced issues with the original code. But the idea is still the same. Detect a "true" page unload and try to teardown the page by "resetting" problematic controls (a list that got smaller which each maui release as the maui team seems to have fixed most of the initial memory related issues). SfCombobox was causing complete page leaks for us, though we have a working workaround for that (without disconnecting the handler) in our teardown code: For a normal SfListView it's more complicated. For us it is not causing page leaks but massive native memory leaks (unmanaged code). Because of that we are using the handler.disconnect there as told by syncfusion. In the past we disposed the platformView instead of disconnecting the handler, which instead caused an already disposed exception sometimes. So probably the correct way would be to disconnect the handler AND dispose it's native view (like in the original MemoryToolkit) Their might be a different way (like for SfCombobox) for SfListView. We were able to pinpoint the leaks to some internal control "VisualContainer" and SF proposed the following solution (which is a bit different from what our memory manager does currently and we did not yet test it): At all we are very happy with the syncfusion controls (using a bunch of them since xamarin.forms days) and they always respond and fix issues fast. But these memory related things are a bit problematic :-( I let you know if i find a more stable solution. I will probably also give your workaround a try. But i will be on holidays for 2 weeks, so i will probably have no news beforce second week of january. Regards, Bernd |
The "constructor workaround" does not seem to work, as the issue was reported again by a tester. So next I'm trying to manually clean up SfComboBoxes/SfListView... |
I noticed some differences after upgrading to the newest version of the syncfusion controls (no more native memory leaks, even without disconnecting handlers). I also did some tests with .net9 and it seems that memory usage is better with .net9. I also do not need to call DisconnectHandler with .net9 as this is done by default. Still doing my usual cleanup when unloading the page(but without manual disconnecting handlers or disposing native views). The .net9 version is now going to the test stage. Will report after it has been stress tested.... Regarding the one with the KeyboardManager. We had this too in the past, but this code in our TearDown logic resolved this (never happend again): |
We've begun seeing these errors in .NET 9, for seemingly simple
They occur for us, when WebAuthenticator window has opened, and app is put to sleep while the authenticator window is open. Which is fairly often, when users need to move from the auth window, into Authenticator app for TOTP tokens etc. |
@frederikspang You might consider to set HandlerProperties.DisconnectPolicy="Manual" on the entry field to test if that fixes the issue. However this might indicate a bug. If you have a reproducible sample project that would probably help the maui team to track it down. When the problem only occurs when the app is put to sleep this might indicate that the 'magic code' now doing the disconnect in .net9 is called to soon. Not every page.Unload is a real one. I had to spend some days to figure out the correct way to call my teardown code in .net8 and the only reliable solution for me was to override the destroy method of the page (which is only available when using prism). Not sure how it is wired in .NET9. However the workaround in the next post is working for me. |
@formerlymisterhenson This is interesting. I just checked my event logs from the test environment. No crashes, but lots of events triggered by your workaround (which i implemented to see if it can notify me about the issue). I am using this code, which seems to work for me as workaround (together with calling KeyboardAutoManagerScroll.Disconnect() on page.Unload or page.Destroy (only available with prism)):
|
The default disconnect policy should be automatic on net9. But I found out that my handler's disconnect method is never called even in net9. So i'm not sure that is true. |
I am getting the same error when sleep/resume the app, can you please suggest me what the solution to fix this? Crash report: Failed to marshal the Objective-C object 0x111b03200 (type: Microsoft_Maui_Platform_MauiTextField). Could not find an existing managed instance for this object, nor was it possible to create a new managed instance (because the type 'Microsoft.Maui.Platform.MauiTextField' does not have a constructor that takes one NativeHandle argument). |
For some days we're running our app with the concurrent garbage collector disabled ( |
@formerlymisterhenson Good you found a workaround which is working for you. But as we now have several people reporting the issue you should probably reopen it so that the maui team can investigate. |
For our app, by now, disabling the concurrent garbage collector seems to prevent the crashes. |
I'm seeing this pretty frequently atm to the point its almost crashing in every other session of running our iOS app. |
You have a problem with strong references. You may be using weak references everywhere. Check again the parent of the parent of your page until you find where it is used. Make sure you keep a strong reference on everything that needs to stay. |
I tried this class as the platform view in a handler. However, since the error is so random. It's hard to confirm that it solved the issue. Adding the missing constructor in MauiTextField itself will probably resolve the issue completely.
|
I have that issue when my code uses the .Parent property. Removing all access to that property fixes the underlying random issue. |
I believe inserting the constructor below in MauiTextField will resolve the problem. My fix above to change the platform view via a handler is a workaround using the hidden NSObject.Handle property
|
Apple platform
iOS
Framework version
net9.0-*
Affected platform version
VS 2022 17.12
Description
We have received feedback from users experiencing random crashes in our app, which have led to some instances of data loss. The app, used for creating and managing health records, is encountering issues with "marshaling Objective-C objects" like MauiTextField and ContentView.
Steps to Reproduce
Unfortunately, we are unable to provide specific steps to reproduce the issue, as the crashes appear to occur randomly. The issue seems to be related to "marshaling Objective-C objects" like MauiTextField and ContentView, but there is no consistent pattern or specific actions that reliably trigger the error. We are continuing to monitor the situation and gather more information in hopes of identifying any potential triggers. Based on the nature of the issue, we believe it may be related to xamarin-macios. We don't think this happens on Windows, but as dotnet/maui#21485 exists, we are not that sure about this.
Did you find any workaround?
No 😔
Relevant logs
No response
The text was updated successfully, but these errors were encountered: