Skip to content

Reset the TP2 environment between mod installations - #372

Open
4Luke4 wants to merge 9 commits into
WeiDUorg:develfrom
4Luke4:agent/issue-342-clean-install-environment
Open

Reset the TP2 environment between mod installations#372
4Luke4 wants to merge 9 commits into
WeiDUorg:develfrom
4Luke4:agent/issue-342-clean-install-environment

Conversation

@4Luke4

@4Luke4 4Luke4 commented Jul 27, 2026

Copy link
Copy Markdown

Summary

  • Restore a clean process-level TP2 variable and array baseline before each top-level TP2 context.
  • Clear mod-defined macros, functions, READLN state, inlined files, and the BCS IDS cache between mod contexts.
  • Preserve temporary metadata lookups performed inside Var.var_clear_push / Var.var_pop.
  • Avoid a hardcoded allow-list of process-owned variables by capturing the clean environment before the first TP2 metadata variables are assigned.

Problem

WeiDU can install, temporarily uninstall, and reinstall multiple mods within one process.

During an automatic uninstallation/reinstallation chain, a subsequent TP2 context could inherit variables and other interpreter definitions created by the preceding mod. This allowed state from one mod installation to affect another mod that happened to be reinstalled by the same WeiDU process.

The reproduction attached to issue #342 demonstrates the problem using three test mods:

  1. Install A7-Mod1.
  2. Install A7-Mod2.
  3. Install A7-Mod3.
  4. Reinstall A7-Mod1.

Reinstalling the first mod causes WeiDU to temporarily uninstall and subsequently restore the later mods. Before this change, the restored mods inherited the first mod's variable values.

Implementation

The fix centralizes TP2 environment initialization in Tpstate.

Before entering a top-level TP2 context, WeiDU now restores copies of an initial environment snapshot containing:

  • local variables;
  • globally scoped variables;
  • local arrays;
  • globally scoped arrays.

The snapshot is captured lazily before TP2-specific metadata such as TP2_AUTHOR, TP2_FILE_NAME, TP2_BASE_NAME, and MOD_FOLDER is assigned.

This preserves legitimate process-level values, including architecture, game, and command-line state, without hardcoding their names.

The reset also clears mod-owned state that must not cross TP2 boundaries:

  • action and patch macros;
  • action and patch functions;
  • queued READLN values;
  • inlined files;
  • the BCS IDS map.

Temporary metadata evaluation performed inside an existing variable or array stack is intentionally excluded from the reset.

This preserves the existing Var.var_clear_push / Var.var_pop behavior used while formatting log entries and prevents those lookups from disturbing an active installation environment.

State remains available across components belonging to the same TP2. Cleanup occurs only when WeiDU enters another top-level TP2 context.

Scope

The production change is confined to:

  • src/tpstate.ml

Validation

A temporary GitHub Actions workflow was used to perform a controlled baseline-versus-fix reproduction with the original testmods.zip attachment from issue #342.

The workflow independently:

  1. built unmodified devel;
  2. built this branch;
  3. downloaded and extracted the original issue fixture;
  4. installed A7-Mod1, A7-Mod2, and A7-Mod3;
  5. reinstalled A7-Mod1, triggering temporary removal and restoration of the later mods;
  6. captured the WeiDU output, debug logs, fixture contents, and command exit statuses.

The temporary validation workflow was removed after the evidence was collected, leaving only the production change in the final branch diff.

Baseline: unmodified devel

The original code reproduced both variable leaks:

local_var #2: First mod variable
!!! Leaked variable detected !!!

local_var #3: First mod variable
!!! Leaked variable detected !!!

The reinstall operation failed:

STATUS[install-mod1]=0
STATUS[install-mod2]=0
STATUS[install-mod3]=0
STATUS[reinstall-mod1]=3

This branch

With this change, each restored mod observed its own variable value:

local_var #2: Second mod variable
local_var #3: Third mod variable

No Leaked variable detected warning was emitted, and the complete installation/reinstallation chain succeeded:

STATUS[install-mod1]=0
STATUS[install-mod2]=0
STATUS[install-mod3]=0
STATUS[reinstall-mod1]=0

CI result

Build Compilation Variable leak reproduced Reinstall result
Unmodified devel Passed Yes Exit status 3
This branch Passed No Exit status 0

The baseline job failed because the supplied fixture detected the original leaked-variable behavior. The fixed-branch job passed.

View the temporary baseline-versus-fix validation run

Additional validation performed:

  • traced the normal handle_tp initialization path;
  • traced the inline restoration path used for temporarily uninstalled components;
  • reviewed the temporary metadata lookup path used while producing log output;
  • compiled both the unmodified and patched source successfully under OCaml 4.14.2 with unsafe strings enabled;
  • verified that the final branch diff modifies only src/tpstate.ml;
  • verified that the pushed source blob matches the locally reviewed blob;
  • performed a structural syntax check for balanced OCaml comments, strings, parentheses, brackets, and braces.

Fixes #342

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.

Mod installations should always start with a clean environment

1 participant