Skip to content

Fix EVABoundFix NRE loop on null KFSM state (#19)#20

Open
edujoliver wants to merge 1 commit into
FirstPersonKSP:masterfrom
edujoliver:fix/evaboundfix-nre-loop
Open

Fix EVABoundFix NRE loop on null KFSM state (#19)#20
edujoliver wants to merge 1 commit into
FirstPersonKSP:masterfrom
edujoliver:fix/evaboundfix-nre-loop

Conversation

@edujoliver

Copy link
Copy Markdown

Summary

Fixes #19.

EVABoundFix.Hook unconditionally constructs a new EVABoundFix whose private constructor dereferences eva.On_bound_fall, eva.On_bound_land and eva.st_bound_fl directly:

myeva.On_bound_fall.OnCheckCondition = Replacement_On_bound_fall_OnCheckCondition;
myeva.On_bound_land.OnCheckCondition = Replacement_On_bound_land_OnCheckCondition;
// ...
for (int i = 0; i < myeva.st_bound_fl.StateEvents.Count; ++i) { ... }

Under some conditions — certain custom EVA suits, partially-loaded vessels, or specific mod combinations — one or more of those KFSM fields are still null when Hook is called. The resulting NullReferenceException is not caught.

Because FirstPersonEVA.Update() calls Hook every frame whenever it detects a fresh KerbalEVA, a single broken state produces an NRE at ~60 messages per second, flooding Player.log (the report in #19 measured ~250 NREs over ~5 seconds) and degrading frame time.

Fix

Validate eva, eva.vessel, and the three KFSM fields before constructing EVABoundFix. If any is null, log the reason once and return cleanly. The mod silently skips Hook for that particular EVA — the fields will populate later in normal cases and Hook will succeed on the next call.

if (eva.On_bound_fall == null) { LogSkipOnce("eva.On_bound_fall is null"); return; }
// ...
EVABoundFix temp = new EVABoundFix(eva);

A small HashSet<string> dedups the skip log so a persistent problem logs exactly once per distinct reason instead of every frame. No new allocations on the happy path.

Verification

Tested locally on KSP 1.12.5 with the equivalent change applied via an external Harmony Prefix patch (TTE_Fix). The previously continuous NRE flood disappeared; Player.log now contains at most one line per broken state, and the per-frame time spent in exception handling is eliminated.

Notes

  • +41 lines total, most of which is comment + the per-field check block.
  • No behavior change on the happy path: when all fields are non-null, the original constructor runs as before.
  • No allocations or work added when Hook succeeds (the HashSet.Add only fires on the skip path).

EVABoundFix.Hook unconditionally constructs a new EVABoundFix, whose
constructor dereferences eva.On_bound_fall, eva.On_bound_land and
eva.st_bound_fl directly. Under some conditions (certain custom EVA
suits, partially-loaded vessels, specific mod combinations) one or
more of those fields are still null when Hook is called.

Because FirstPersonEVA.Update() invokes Hook every frame, a single
broken state produces a NullReferenceException at ~60 messages per
second, flooding Player.log and degrading frame time.

Validate the relevant fields before constructing EVABoundFix and skip
silently if any is null. Skip reasons are deduplicated so a persistent
problem logs exactly once per reason instead of every frame.

Fixes FirstPersonKSP#19
@linuxgurugamer

Copy link
Copy Markdown
Collaborator

@JonnyOThan Can you take a quick look at this. Looks ok to me, but I don't have a lot of time right now

@JonnyOThan

Copy link
Copy Markdown

I don’t either but I will review this next time I’m looking at this mod. It’s definitely a problem, but I want to make sure this is the right fix.

@linuxgurugamer

Copy link
Copy Markdown
Collaborator

I don’t either but I will review this next time I’m looking at this mod. It’s definitely a problem, but I want to make sure this is the right fix.

Ok. Ping me with your conclusion, if it's ok I can then do a quick build/release

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

EVABoundFix..ctor NullReferenceException loop on vessel switch

3 participants