Skip to content

fix(libkernel): bind deferred initialization to the loaded image - #4419

Merged
oneandonlydean merged 1 commit into
boykopovar:mainfrom
Ondra97:codex/deferred-module-lifetime
Oct 12, 2026
Merged

oneandonlydean merged 1 commit into
boykopovar:mainfrom
Ondra97:codex/deferred-module-lifetime

Conversation

@Ondra97

@Ondra97 Ondra97 commented Oct 12, 2026

Copy link
Copy Markdown
Contributor

What

On Windows, a deferred guest module reloaded at the same base address returns a valid load handle without running its entry or constructors. InitializeDeferredModule keeps a process-wide set of native base addresses after the images have been unloaded. It also marks an image initialized before its entry has finished, so another thread can return from a load while initialization is still blocked.

Keep the state in the mapped initialization table. Completion consumes its entry/count header; Windows restores the original file-backed table on the next actual load. An image retained by another guest or native reference stays initialized. A different thread waits for completion, and recursive loading by the initializing thread retains its existing behavior. The loader restores the metadata page protection and wakes waiters when initialization ends. An initialization exception marks the current image failed until it is unloaded.

The existing table layout and initializer pointer slots are preserved. Document the mapped state in Architecture and add Windows regression fixtures for reload, native pinning, concurrent initialization and recursive loading.

Tested

Windows x86-64, Release, supported WinLibs GCC 15.2.0 UCRT/POSIX/SEH r7; real libkernel/libc APIs and a module produced by the relinker.

  • Before the fix, reload, native-pin reload and concurrent-load regressions failed; recursive loading passed.
  • Full build completed successfully. Full CTest: 942 passed, 6 expected skips, 0 failures across 948 tests. The Windows skip checker accepts all six skips; the longest test took 19.99 seconds.
  • The four new tests and existing dynamic-loader/module-info tests each passed ten consecutive runs. The new tests also verify the entry result, separate entry/constructor counts, actual native unload and restored metadata protection.
  • A synthetic ELF module converted with --windows --module-dir passed reload and external-pin cases with the unchanged metadata format.
  • The original three-load reproduction improved from 1/3 initialized loads to 3/3, with entry and constructor called exactly once per lifetime and no duplicate initialization for additional references.
  • Registration check: 699 test executables, none missing from CTest.
  • Conventions passed for the commit, title and completed PR template. The repository's overlap checker found no overlap with open pull requests.

Linux/macOS runtime, initializer exception propagation and a PS5 title were not exercised locally. The production change is inside the Windows deferred-loader path.

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed in TechnicalDebt
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Unblocks: none
  • AI-assisted: yes

@github-actions

github-actions Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.

Pull request Conflicting files (lines on main) Same exports Same new files
#4593 core/libs/prx/libkernel/Module/src/DynamicLoader.cpp L12

@oneandonlydean
oneandonlydean merged commit 30e1691 into boykopovar:main Oct 12, 2026
9 checks passed
@Ondra97
Ondra97 deleted the codex/deferred-module-lifetime branch October 17, 2026 14:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants