From 1ceeae13d2a84ea6f105d568529f3cd256ffb16d Mon Sep 17 00:00:00 2001 From: Koichi Sasada Date: Sat, 13 Dec 2025 03:22:04 +0900 Subject: [PATCH] call Thread.pass just after Thread.stop The following `test_irb_fg_jobs_and_kill_commands` expects that after `fg 0` Thread#1 should be `sleep_forever`. ```ruby def test_irb_fg_jobs_and_kill_commands out = run_ruby_file do type "irb" type "fg 0" type "jobs" type "kill 1" type "exit" end assert_match(/#0->irb on main \(#: running\)/, out) assert_match(/#1->irb#1 on main \(#: stop\)/, out) end end ``` However, the following switching method expects that ``` def switch(key) th, irb = search(key) ... th.run Thread.stop ``` (1) resume target thread (2) Suspend current thread (-> sleep_forever) `th.run` calls `Thread.pass` internally and maybe the context swtich to resumed thread (#0 in this case). Thread #0 should switch to #1 before `jobs` command. Until Ruby 3.4, I/O operation makes context switching to another ready thread, so that several I/O output can resume `#1`. However, our planning new thread scheduler delays context switching on I/O operations, so the thread #1 still running (because `Thread.stop` is not called yet). This patch add `Thraed.pass` to make workaround for this test. --- lib/irb/ext/multi-irb.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/irb/ext/multi-irb.rb b/lib/irb/ext/multi-irb.rb index 9f234f0cd..71a50ff29 100644 --- a/lib/irb/ext/multi-irb.rb +++ b/lib/irb/ext/multi-irb.rb @@ -65,6 +65,7 @@ def switch(key) @current_job = irb th.run Thread.stop + Thread.pass @current_job = irb(Thread.current) end @@ -220,6 +221,7 @@ def IRB.irb(file = nil, *main) # :nodoc: end end Thread.stop + Thread.pass @JobManager.current_job = @JobManager.irb(Thread.current) end