Closed kalimag closed 3 months ago
I think the easiest solution would be to turn ToolManager._tools
from a List<T>
into an ImmutableArray<T>
. I can't think of any mutable collection type that has the same APIs and can safely be modified during enumeration, and making defensive copies for every enumeration would be wasteful. Modifying the _tools
collection is not common so I imagine the perf should be insignificant.
I can open a PR for this if you agree.
No, it needs to be mutable. Calling Oh, I see you meant a copy-on-write. That might also work, but your worries about the overhead would be misplaced, since it's a very small array of references (ToArray
is correct.nuint
s).
Yeah, that's what I mean. It's a choice between making a defensive copy every time the field is enumerated (multiple times every frame) or copy on write when a tool is opened/closed.
I realize either way it's not a measurable perf hit on its own, but the latter seems much cleaner to me.
Summary
If a tool is directly or indirectly opened or closed from Lua, in many cases a collection changed exception occurs in
ToolManager
and BizHawk crashes.There are a few different ways this can happen, but all come down to
ToolManager._tools
being modified within one of the variousforeach (var tool in _tools)
loops.Presumably the same problem exists with external tools that cause other tools to be opened/closed from
Update...
andRestart
.Repro
Various ways to trigger the issue, there may be more:
This example also works from the Lua Console:
Some others:
Output
Stack trace may differ depending on what event caused the tool open/close.
Host env.