-
Notifications
You must be signed in to change notification settings - Fork 339
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 #2355
Comments
Daggerfall Crashes 2022-06-17_18.zip Oops, failed to actually upload the crash data. |
I'm mainly seeing a lot "index out of range" exceptions in your error logs, which are mod-related (Loot Menu Mod).
Please remove all mods before opening an issue to confirm your stability problems are actually with base Daggerfall Unity or have been introduced by mods. If the crashing only happens with mods installed, please try to isolate which one and raise with creator of that mod. I'm not aware of any crashing issues like this in base DFU. I am happy to investigate further if you can reproduce with no mods installed. For good measure, please setup fresh using the recommended DaggerfallGameFiles method. If you're using repacks made by others (such as the GOG Cut), I specifically do not provide support for these distributions. |
Edit: I am interested in discussion about this one, and feel that I closed out of hand. From what you're saying a large number of mods is basically a prerequisite to trigger the problem. I'll open back up for now. I'll also tag @KABoissonneault. I'd love to know his thoughts on the thread safety question, if possible. And since you mention Travel Options, maybe @ajrb can chime in. |
I'm not sure. At first, I thought it was possible For sure, solution B could be beneficial regardless of concurrency issues. As suggested in the page for Overall, I'm not sure DFU is directly at fault for the crash, as everything is in game thread. World of Daggerfall is probably the source of dynamically spawned enemies (they can spawn any time a terrain loads). While the terrain system uses the UnityJobs system, all the events are called on the Game thread from what I can see, so again WoD would only spawn enemies on the game thread. But since I don't think the change would hurt DFU, while potentially increasing mod stability, I think we can do it. Want me to tackle this one? |
An Access Violation would typically be generated by reading a collection while members are being removed. So I would expect this to happen if |
That's an interesting idea. The underlying
AFAIK other uses should only trigger during game thread.
I'm always happy to have your help Kab. :) If this is something you feel would help with performance in WoD and other mods, then we should discuss. There are a few concerns on my end (e.g. tracking destroyed and disabled enemies as well) but I trust we'll be able to sort that out. For now, I'm mainly wanting to dive into Trabber's hypothesis. Regarding performance, I built the NearbyObjects system to help centralise and offload scene searches for several object types. It's not quite realtime (updates 3 times a second) but I think that would be adequate to replace most uses of |
I think there is one point of my hypothesis I did not communicate well. I am not worried about 2 instances of Methods which my hypothesis say should not be allowed to run concurrently with
The highest risk comes from the first type of activity which is why I mentioned With that said, I still don't know how to tell what runs on which thread. But, my gut tells me Edit: I also have not figured out how the engine becomes aware of a GameObject, I am starting to assume it just happen automatically in the constructor or something. |
AFAIK there's no use of DestroyImmediate in play. It's only used in context of editor (which is fine). Unity generates a warning in the output logs we'd see if DestroyImmediate was called during play context. The Water component you mention is part of Unity's own Standard Assets package and is not attached to anything in DFU. I do understand what you're saying though. My approach above is to limit how often FindObjects scene searches are called to the one pathway. This is easy to do within the current framework and doesn't require much refactoring. I'm trying to start from a point of "least impact" since the actual cause of your crashes is technically unknown, and doesn't occur in unmodded DFU that I'm aware of. I'm resistant to making large changes just yet. |
Sounds good and practical. Thanks for looking at it. |
Just FYI, I was doing an unrelated playtest with a player just now, and they've reproduced this crash. Pretty clear from the callstack
Here's the full logs |
Thanks Kab. To give me a bit more info, what was player doing in game at time of crash? Were they in a dungeon, travelling across overworld, etc? |
They say they were in a dungeon. Kind of surprising to be honest, I didn't think there would much things in parallel in there. |
Cheers, that's good to know. Thinking about this one further, the way EnemySenses works here is pretty aggressive even without parallel threads. There's a throttle in place so this isn't running 60 times a second per enemy or anything, but it's still a lot of extra load and potential for trouble. I'm going to make this one a priority for 0.14.1 and release an update in another week to start remediating the excessive use of FindObjectsOfType in core. Thank you both for all your input. |
I didn't end up giving this one the priority promised, I'm sorry. I'm actually somewhat curious if the recent engine patch also helps remediate the access violation inside engine. I'm not sure that's easy to test however, and probably better just for me to move forwards with the changes I have in mind to reduce how frequently FindObjectsOfType is used in core. I'll loop back to this one when I can. |
Just bumping this to mention that the crash is still happening out there. Probably one of the more important things we should fix in the next update |
My time is somewhat constrained, but I find this to be an interesting issue. As expected based on the lack of detailed symbols in the logged stack, [MethodImpl(MethodImplOptions.InternalCall)]
[TypeInferenceRule(TypeInferenceRules.ArrayOfTypeReferencedByFirstArgument)]
[FreeFunction("UnityEngineObjectBindings::FindObjectsOfType")]
public static extern UnityEngine.Object[] FindObjectsOfType(Type type); Given this, I decided to look at what kind of artifacts were in the zip @Trabber provided (still entirely new to this project, so I didn't know what to expect). It was nice to see a memory dump, and even nicer of Unity to provide symbols: https://docs.unity3d.com/Manual/WindowsDebugging.html Loading up one of the crashdumps in WinDbg and running
From the hip, it looks like the pointer to
The next (non-inlined) frame up, things look like they are okay.
Unfortunately, it's quite time consuming to dive further into this matter without source access. I've looked a bit with Ghidra, but did so before I realized symbols and crashdumps were available. Maybe I can put some further time into this with the goal of verifying lack of thread safety. Edit: I looked at the native stacks for all three crashes, and they're the same. However, one other thing: the stack above is
|
No need, I want to handle this one. I just gotta do it before the 1.1 release |
Should be fixed in #2605 |
Darn near 6 years later than I last paid attention to this project, all I
have to say is that you are epic. Beautiful solution to a whole range of
potential issues. I need to make time for gaming again.
…On Sat., Apr. 6, 2024, 11:42 Kévin Alexandre Boissonneault, < ***@***.***> wrote:
Should be fixed in #2605
<#2605>
—
Reply to this email directly, view it on GitHub
<#2355 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AD2U6J54SBDGGTEQBEZG3J3Y4AXYDAVCNFSM5ZFMHTBKU5DIOJSWCZC7NNSXTN2JONZXKZKDN5WW2ZLOOQ5TEMBUGEYTIOBRGIZQ>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
I have gotten 3 crashes in 2 days. After poking around in the logs, and the unity docs, and the code here, I am fairly confident that the core cause of all of them is that
UnityEngine.Object.FindObjectsOfType()
is not thread safe.From a game play perspective, there did not feel like any pattern to them, although it looks like technically the last thing I did each time was enter a new area (map pixel or scene). I suspect that I have seen so many and I can't find reports from other people because more mods would make these race conditions more common and I am running something like 80 mods, so most people who get the crash would also attribute this to one or more of these mods. (I reported it to Travel Options first)
Specifically, the crashes are Access Violations in
UnityEngine.Object.FindObjectsOfType()
. In 2 crashes this was called byDaggerfallWorkshop.PlayerGPS.UpdateNearbyObjects()
and it was called byDaggerfallWorkshop.Game.GameManager.AreEnemiesNearby()
in the third.In my experience (10 years as a software engineer, most of that C#) an access violation in a C# app is almost always one of: pinvoke, unsafe code, or a thread safety issue. In particular using any of the .Net collection types which are not explicitly thread safe in a multi-threaded environment can cause Access Violations and that is by for the most common cause I have seen. Looking for other instances of this crash I have found quite a few other unity projects with reports of random crashes on only some user's systems that come from this method, which also sounds like race condition hell to me.
My recommended fixes come in 2 flavors:
A. Try to get Unity to make that method thread safe (if I understand what it is actually doing, that would be really hard).
B. Eliminate uses of this method in any potentially concurrent code, which looks like all 19 uses of this function in daggerfall-unity to me. And that requires some type of thread safe tracking for the 9 types which this is used to find. I have not looked at the modding API so I do not know how hard it would be to force a factory pattern on those 9 types and it has been so long since I used mono that I have no idea if you have access to weak references which is definitely the easy way to do that type of instance tracking.
I am between jobs right now so I will try to spend some time poking at option B, based on the docs it should come with some performance benefits in addition to being a potential crash fix, also I have never actually used unity before so it might be fun to see how this works. How/where would you like such further investigation communicated?
The text was updated successfully, but these errors were encountered: