Skip to content

Keep each VM on the JDK image file it started with - #39

Merged
Project516 merged 4 commits into
masterfrom
p516/image-fd-per-vm
Nov 4, 2026
Merged

Project516 merged 4 commits into
masterfrom
p516/image-fd-per-vm

Conversation

@Project516

@Project516 Project516 commented Nov 4, 2026 •

Copy link
Copy Markdown
Owner

Since #37, Node reads the JDK image (build/jdk/lib/modules, or jdk/image.jar in the package) through descriptors that stay open. They were shared by every VM in the process and keyed only by path.

So if an upgrade replaced the package in place (a new image.jar and boot.pack renamed over the old ones) while a server process kept running, a VM started after the upgrade would read the new boot.pack index with offsets into the new image, but through the descriptor of the old, replaced file. That returns the wrong bytes for every class not in a pack.

  • imageFd now keys open descriptors by path and inode, so a replaced file gets a new descriptor.
  • Each backend (ImageBackend, and NodeBackend for build/jdk) takes its descriptor once and keeps it, so a VM reads the image it started with to the end. The replaced file stays readable for it, as an open file does on POSIX.

Each image file a process actually runs on stays open once, as before.

Checks:

  • New test in test/image.test.ts: an image file renamed over the old one is read by a new backend, while one created before keeps reading the old file. With the old cache, the new backend read the old file's bytes.
  • pnpm typecheck and pnpm test pass (145 tests).

Noticed, not fixed:

  • A replaced image file's descriptor stays open for the rest of the process, since a VM started before the upgrade may still read it. That is one descriptor per in-place upgrade while a process runs. Closing it would need each VM to release its image when it exits.

@coderabbitai

coderabbitai Bot commented Nov 4, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 38 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: c16d9ebc-6dc6-41be-b642-cf3696706f12
Commits

Reviewing files that changed from the base of the PR and between 1c7e4f2 and b5725e2.

Files selected for processing: 3
  • src/image.ts
  • src/node.ts
  • test/image.test.ts
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@project516-review-bot project516-review-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR fixes a bug where VMs would read the wrong JDK image file after an in-place upgrade. Previously, imageFd cached file descriptors by path only, so a replaced file (same path, new inode) would be read through the old descriptor. Now imageFd keys by path and inode, and each backend (ImageBackend, NodeBackend) retains its own descriptor per image file, so a VM continues reading the image it started with. The new test verifies that a backend created before a rename keeps reading the old file while a new backend reads the new file.


review-bot, model nvidia/nemotron-3-ultra-550b-a55b:free, verdict approve

@project516-review-bot project516-review-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR fixes a bug where in-place JDK image upgrades caused VMs to read wrong bytes. The imageFd cache now keys descriptors by path and inode, so a replaced file gets a new descriptor. Each ImageBackend and NodeBackend instance caches its own descriptor at first use, so a VM continues reading the image it started with. A new test verifies that a backend created before a rename keeps reading the old file while a new backend reads the new file. The known limitation (descriptors accumulate per upgrade) is acknowledged.


review-bot, model nvidia/nemotron-3-ultra-550b-a55b:free, verdict approve

@project516-review-bot project516-review-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR fixes a bug where in-place JDK image upgrades caused VMs started after the upgrade to read the new boot.pack index through the old image file's descriptor, returning wrong class bytes. The fix keys the global descriptor cache by path+inode so replaced files get new descriptors, and each backend (ImageBackend, NodeBackend) caches its own descriptor per image file at first use so a VM reads the image it started with. A new test verifies the behavior. The known trade-off (descriptors accumulate across upgrades) is documented.


review-bot, model nvidia/nemotron-3-ultra-550b-a55b:free, verdict approve

@project516-review-bot project516-review-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR fixes a bug where an in-place JDK image upgrade would cause VMs started after the upgrade to read the new boot.pack index through the old image file's descriptor, returning wrong class bytes. The fix keys the global descriptor cache by (path, inode) so a replaced file gets a new descriptor, and each backend instance caches its own descriptor at first use so a VM reads the image it started with for its lifetime. A new test verifies the old backend keeps reading the old file after a rename upgrade while a new backend reads the new file.


review-bot, model nvidia/nemotron-3-ultra-550b-a55b:free, verdict approve

@Project516
Project516 merged commit 9afafdf into master Nov 4, 2026
16 checks passed
@Project516
Project516 deleted the p516/image-fd-per-vm branch November 4, 2026 23:47
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.

1 participant