mirror of
https://github.com/ruby/ruby.git
synced 2026-10-28 16:36:20 +08:00
thread: leave RB_WAITFD_PRI waits to the blocking path
waitfd_to_waiting_flag maps RB_WAITFD_PRI to no thread_sched_waiting_* event, so the M:N scheduler registered nothing for it yet parked the thread: a timeout-less IO#wait(IO::PRIORITY) on an M:N thread slept forever (a VM_ASSERT in thread_io_wait_events on debug builds). Exclude it from thread_io_mn_schedulable; poll(2) on the blocking path handles POLLPRI. The test lives in test/ruby/test_ractor.rb rather than bootstraptest because it needs the socket extension, which btest runs without. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
6f176c8925
commit
4e4e3ded8b
2 files changed
+28
-1
Notes:
git
2026-08-14 16:36:03 +00:00
No files matched your search
@@ -771,4 +771,27 @@ class TestRactor < Test::Unit::TestCase
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
|
||||
def test_io_priority_wait_on_mn_thread
|
||||
omit 'POLLPRI/MSG_OOB semantics differ on windows' if RUBY_PLATFORM =~ /mswin|mingw/
|
||||
# A timeout-less IO#wait(IO::PRIORITY) on an M:N thread must take the
|
||||
# blocking path: the M:N scheduler has no event for POLLPRI and used to
|
||||
# register nothing yet park the thread forever.
|
||||
assert_separately([], __FILE__, __LINE__, <<-'RUBY')
|
||||
Warning[:experimental] = false
|
||||
require 'socket'
|
||||
r = Ractor.new do
|
||||
serv = TCPServer.new("127.0.0.1", 0)
|
||||
c = TCPSocket.new("127.0.0.1", serv.addr[1])
|
||||
s = serv.accept
|
||||
t = Thread.new { c.wait(IO::PRIORITY, nil) }
|
||||
sleep 0.5
|
||||
s.send("!", Socket::MSG_OOB)
|
||||
woken = t.join(5)
|
||||
[serv, c, s].each(&:close)
|
||||
woken ? :ok : :timeout
|
||||
end
|
||||
assert_equal :ok, r.value
|
||||
RUBY
|
||||
end
|
||||
end
|
||||
@@ -2055,7 +2055,11 @@ static bool
|
||||
thread_io_mn_schedulable(rb_thread_t *th, int events, const struct timeval *timeout)
|
||||
{
|
||||
#if defined(USE_MN_THREADS) && USE_MN_THREADS
|
||||
return !th_has_dedicated_nt(th) && (events || timeout) && th->blocking;
|
||||
// RB_WAITFD_PRI has no thread_sched_waiting_* event: the scheduler would
|
||||
// register nothing and park the thread forever. POLLPRI works on the
|
||||
// blocking path.
|
||||
return !th_has_dedicated_nt(th) && (events || timeout) && th->blocking &&
|
||||
!(events & ~(RB_WAITFD_IN | RB_WAITFD_OUT));
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
|
||||
Reference in new issue
Block a user