GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Allow using vthreads for all Ruby threads by headius · Pull Request #9789 · jruby/jruby

Conversation

@headius

@headius headius commented Oct 9, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

Allow virtual threads for Ruby-created threads through jruby.thread.vthread; this branch enables them across CI for testing. Fiber backing remains independently controlled by jruby.fiber.vthread.

Initialize Ruby thread identity, group, registration and inherited interrupt masks before execution, and preserve Ruby priority readback/inheritance. Offload native process waits to platform workers with errno and interrupt handling preserved, and park fiber creators during backing-thread adoption to avoid carrier starvation. Fresh-JVM specs explicitly exercise both Ruby thread backing modes, lifecycle/priority behavior, process status and concurrent fiber results.

Local validation: all 14 reproductions matching failed CI JDK 21/25/27 configurations pass with explicit false/true controls; the full slow MRI selection passes (177 tests), and spec:jruby passes (86 examples, 3 existing pending). Fast RubySpec also passes (31,823 examples, 0 failures/errors, 1,703 tagged). Focused specs pass interpreted, forced-compiled and JIT0 modes. Broader Thread/Fiber/Process/Open3 runs retain an unrelated empty-environment Java lookup failure and one platform-mode signal startup flake.

CI is not yet fully green: the previous JRuby CI run had two reproduced scheduling regressions addressed here; its cancelled JDK 21 stdlib job logged no test name and remains unlocalized. New-head CI is pending.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@headius headius added this to the JRuby 10.1.3.0 milestone Oct 9, 2026
@headius
headius marked this pull request as draft October 9, 2026 01:06
@headius
headius force-pushed the all_virtual_threads branch from f8ba86f to 69a6490 Compare October 9, 2026 01:11
@headius

headius commented Oct 9, 2026

Copy link
Copy Markdown
Member Author

Surprisingly, making all threads be vthreads did not break a single test.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@headius
headius force-pushed the all_virtual_threads branch from 69a6490 to de85fd4 Compare October 9, 2026 02:02
@headius

headius commented Oct 9, 2026

Copy link
Copy Markdown
Member Author

I have switched the feature off for now and it can be safely merged any time. We will want to do more experimentation, and perhaps add a JRuby-specific enhancement to allow opting-in for specific threads (e.g. Thread.new(virtual: true)

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@headius
headius marked this pull request as ready for review October 9, 2026 02:04
@headius
headius force-pushed the all_virtual_threads branch from de85fd4 to 51a13a0 Compare October 9, 2026 02:10
@headius

headius commented Oct 9, 2026

Copy link
Copy Markdown
Member Author

I had the logic flipped, actually. Most builds fail with all threads virtual because virtual threads do not appear to be setting up the RubyThreadGroup correctly. I've flipped it back on with corrected logic to try to get things green.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@headius
headius marked this pull request as draft October 9, 2026 02:10
@headius

headius commented Oct 30, 2026

Copy link
Copy Markdown
Member Author

I threw Codex at this to work out edge cases and explore possible issues for users:

PR #9789: additional changes and user effects

Additional changes

  • Create unstarted virtual threads, allowing JRuby to initialize identity, groups, registration, and interrupt masks before execution. This fixes startup exceptions and cleanup races.
  • Restore jruby.thread.vthread=false by default, matching the intended opt-in behavior.
  • Preserve Ruby priority readback and inheritance, although virtual threads' actual scheduling priority remains fixed.
  • Add regression coverage for default, disabled, and enabled modes under interpretation and compilation. CI passes across JDK 21, 25, and 27.

Likely user effects when enabled

  • Blocking-heavy applications may support more concurrent threads with fewer OS-thread resources. Throughput and memory improvements remain unmeasured; CPU-heavy code gets no inherent speedup.
  • Scheduling and timing can differ. Applications must retain their synchronization.
  • JDK 21 monitor-held blocking can pin carriers; JDK 25 removes that restriction. Native calls can still pin carriers, and libraries relying on OS-thread affinity need application testing.
  • Java interop sees virtual-thread identities; platform-only thread enumeration excludes them.
  • Thread lifecycle, interruption, Ruby/Java locals, and fiber interactions passed targeted tests.

With the default setting, Ruby-created threads remain platform-backed; fiber configuration remains independent.

References

  • PR #9789
  • Fix commit
  • JRuby CI
  • Distribution CI
  • JDK 21 virtual threads
  • JDK 25 virtual threads
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

headius added 2 commits October 30, 2026 13:47
@headius
Allow using vthreads for all Ruby threads
c015caf
Ruby threads have been normal native threads up to now. This patch
allows opting into using virtual threads for Ruby threads, in a
model closer to m:n threading.

New property: jruby.thread.vthread=(true/*false)
@headius
Enable for testing in CI
32aadbc
@headius
headius force-pushed the all_virtual_threads branch from bb81299 to 32aadbc Compare October 30, 2026 18:48
@headius

headius commented Oct 30, 2026

Copy link
Copy Markdown
Member Author

I squashed the relevant changes and pushed a new commit that enables vthreads to shake out more problems.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

headius added 2 commits October 30, 2026 19:48
@headius
Test Ruby thread behavior with both Java backing types
d1f31c6
Replace the regression test's fixed default assumption and repeated startup
program with JRuby-specific behavior examples in explicitly configured fresh
JVMs. Cover backing identity, lifecycle, priority inheritance and deferred
interrupt delivery independently of the parent suite's thread mode.
@headius
Avoid carrier starvation in process waits and fiber startup
3f816ab
Run native process waits on platform workers while preserving errno and
interrupt handling on the Ruby caller. Park fiber creators until their
backing thread is adopted instead of repeatedly yielding.

Cover process status, detach, errno and concurrent fiber results in fresh
JVMs with explicitly enabled and disabled virtual Ruby threads and bounded
carrier pools.
@headius

headius commented Nov 3, 2026

Copy link
Copy Markdown
Member Author

Lots of brute-force testing here so I've mostly been letting agents do it. Additional fixes are coming. This won't be enabled by default, but I'm trying to shake out as many issues with the vthread mode as possible.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

headius added 4 commits November 3, 2026 03:51
@headius
Avoid JDK 21 carrier starvation during class mutation
38552ab
Use the same intrinsic monitor for all weak subclass-set operations.
A parkable lock can unmount a waiter that later needs a carrier while
other threads pin all carriers under the hierarchy monitor.

Preserve mutual exclusion for weak-map cleanup during reads. Existing
class-concurrency coverage passes repeated bounded-carrier controls and
MRI Class/Module tests in both Ruby thread backing modes.
@headius
Close fiber schedulers outside the Ruby thread monitor
2f0fd83
Scheduler close can resume fibers and wait for them. Holding the thread
monitor pins JDK 21 carriers during this handoff and can prevent the
fibers from ever running.

Guard disposal entry separately and publish completion after scheduler
close, keeping scheduler joiners blocked until teardown is complete.
Finish cleanup in a finally block without suppressing callback errors.

Add fresh-JVM coverage for scheduler shutdown with explicit virtual and
platform Ruby threads. The enabled case detects the old deadlock with a
single carrier; the disabled control passes.
@headius
Merge branch 'master' into all_virtual_threads
d0e4451
@headius
Fix fiber block parameter after merging upstream
b01b896
Restore the fiberBlock parameter name used by upstream frame cloning.
The merge retained the old block parameter, duplicating the local block
variable and leaving fiberBlock undefined, so all JRuby builds failed.

Keep both per-fiber frame cloning and the CompletableFuture startup
handoff from the virtual-thread fixes.
@headius headius modified the milestones: JRuby 10.1.3.0, JRuby 10.1.4.0 Nov 4, 2026
headius added 2 commits November 5, 2026 05:50
@headius
Avoid carrier starvation while selecting shared channels
bf49f38
Release the channel blocking monitor across selector waits and restore
its original blocking mode only after the final concurrent selector is
deregistered. Run blocking Java selector calls on platform workers for
virtual Ruby threads, keeping Ruby event polling and cleanup on the caller.

Cover concurrent accepts, targeted interruption, server reuse and closing
pending acceptors in fresh JVMs with explicit backing modes.
@headius
Merge master into all_virtual_threads
d63dc68
Preserve shared-channel selection and virtual-thread selector offloading
while taking currentSelector away under its wakeup lock before pooling.
Retain upstream monitor wakeups and monotonic thread-join behavior.
@headius
headius marked this pull request as ready for review November 12, 2026 00:35
@headius

headius commented Nov 12, 2026

Copy link
Copy Markdown
Member Author

There's a lot of changes that still need to be reviewed.

A few quick ones:

  • Selection logic has large changes and also now stored a JRuby-specific class in a static WeakHashMap that will keep a classloader alive potentially longer than it should be.
  • The locking changes in RubyClass don't seem necessary and need to be examined as they switch to a different lock.
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

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

Reviewers

No reviews

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

JRuby 10.1.4.0

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

1 participant

@headius
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.