ConditionVariable#signal is lost when no fiber is waiting. If the scheduler thread stalls for 0.1 seconds after the first signal, Scheduler#run_once resumes the signalling fiber from its timer before the ready waiter, and the waiter then waits forever for a signal that never comes. Count the signals and wait only while none is pending.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Treat encoding coercion, `to_io`, and scheduler capability checks as
callouts that can change the buffer before byte access begins.
- Copy `get_string` bytes through the existing locked-for-reading helper
after encoding coercion, without retaining metadata pointers across it.
- Obtain the writable buffer after `to_io` conversion in `read` and `pread`.
- Reacquire and validate the buffer before native I/O fallback when the
scheduler does not handle `read`, `write`, `pread`, or `pwrite`.
Add regression coverage using the existing buffer and slice APIs. Scheduler
probes shrink a slice without freeing its underlying storage, making stale
length handling observable without accessing released memory. Also cover
encoding callbacks and frozen-state changes during I/O coercion.
This is an independent correctness extraction from #18911. It introduces
no new classes, slice representation, or public API.
nonblock= works there; what does not happen is the write failing. The
peer being closed leaves the next write on an AF_UNIX socket succeeding
instead of raising EPIPE.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
SleepingUnblockScheduler#unblock deliberately breaks the join path,
so the inner Thread.new{sleep(0.01)} created inside Fiber.schedule
is abandoned mid-sleep when the outer thread exits. It eventually
wakes and lingers in Thread.list, breaking cleanup_threads in later
test files (e.g. test/-ext-/thread/test_instrumentation_api.rb).
Capture the inner thread and join it in an ensure.
18) Failure:
TestThreadInstrumentation#test_thread_pass_multi_thread [/build/ruby4.0/test/-ext-/thread/test_instrumentation_api.rb:289]:
<[#<Thread:0x00007f8dbc9b7f48 run>]> expected but was
<[#<Thread:0x00007f8dbc9b7f48 run>,
#<Thread:0x00007f8dbc9f45b0 /build/ruby4.0/test/fiber/test_thread.rb:165 sleep>]>.
Previously, calling IO#flush or closing an IO with unflushed buffered
writes would just invoke `#blocking_operation_wait` and flush the write
buffer using a `write` syscall. This change adds flushing through the
fiber scheduler by invoking the `#io_write` hook.
* Prefer IO::Buffer#write in IOScheduler
* Use Dir.tmpdir for test file
* Correctly handle errors in io_flush_buffer_fiber_scheduler
* Added `Ractor::Port`
* `Ractor::Port#receive` (support multi-threads)
* `Rcator::Port#close`
* `Ractor::Port#closed?`
* Added some methods
* `Ractor#join`
* `Ractor#value`
* `Ractor#monitor`
* `Ractor#unmonitor`
* Removed some methods
* `Ractor#take`
* `Ractor.yield`
* Change the spec
* `Racotr.select`
You can wait for multiple sequences of messages with `Ractor::Port`.
```ruby
ports = 3.times.map{ Ractor::Port.new }
ports.map.with_index do |port, ri|
Ractor.new port,ri do |port, ri|
3.times{|i| port << "r#{ri}-#{i}"}
end
end
p ports.each{|port| pp 3.times.map{port.receive}}
```
In this example, we use 3 ports, and 3 Ractors send messages to them respectively.
We can receive a series of messages from each port.
You can use `Ractor#value` to get the last value of a Ractor's block:
```ruby
result = Ractor.new do
heavy_task()
end.value
```
You can wait for the termination of a Ractor with `Ractor#join` like this:
```ruby
Ractor.new do
some_task()
end.join
```
`#value` and `#join` are similar to `Thread#value` and `Thread#join`.
To implement `#join`, `Ractor#monitor` (and `Ractor#unmonitor`) is introduced.
This commit changes `Ractor.select()` method.
It now only accepts ports or Ractors, and returns when a port receives a message or a Ractor terminates.
We removes `Ractor.yield` and `Ractor#take` because:
* `Ractor::Port` supports most of similar use cases in a simpler manner.
* Removing them significantly simplifies the code.
We also change the internal thread scheduler code (thread_pthread.c):
* During barrier synchronization, we keep the `ractor_sched` lock to avoid deadlocks.
This lock is released by `rb_ractor_sched_barrier_end()`
which is called at the end of operations that require the barrier.
* fix potential deadlock issues by checking interrupts just before setting UBF.
https://bugs.ruby-lang.org/issues/21262
Previously, vm_make_env_each() (used during proc
creation and for the debug inspector C API) picked up the
non-GC-allocated iseq that rb_vm_push_frame_fname() creates,
which led to a SEGV when the GC tried to mark the non GC object.
Put a real iseq imemo instead. Speed should be about the same since
the old code also did a imemo allocation and a malloc allocation.
Real iseq allows ironing out the special-casing of dummy frames in
rb_execution_context_mark() and rb_execution_context_update(). A check
is added to RubyVM::ISeq#eval, though, to stop attempts to run dummy
iseqs.
[Bug #21180]
Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org>
If one thread is reading and another closes that socket, the close
blocks waiting for the read to abort cleanly. This ensures that Ruby is
totally done with the file descriptor _BEFORE_ we tell the OS to close
and potentially re-use it.
When the read is correctly terminated, the close should be unblocked.
That currently works if closing is happening on a thread, but if it's
happening on a fiber with a fiber scheduler, it does NOT work.
This patch ensures that if the close happened in a fiber scheduled
thread, that the scheduler is notified that the fiber is unblocked.
[Bug #20723]
test/fiber/test_queue.rb: Make the stuck tests fail.
We observed the 2 tests in the `test/fiber/test_queue.rb` getting stuck
in some GCC compilers in Ubuntu ppc64le focal/jammy, even when the timeout
`queue.pop(timeout: 0.0001)` is set in the code.
This commit is to make the tests fail rather than getting stuck.
`ppc64le` appears to be struggling with this test due to timeout. Let's see
if reducing the number of iterations can help improve the test performance.