| Age | Commit message (Collapse) | Author |
|
Internal tracepoints only make sense to run globally, and they already
took completely different paths.
|
|
If another ractor is calling for GC, we need to prevent the current one
from joining the barrier. Otherwise, our half-built object will be marked.
The repro script was:
test.rb:
```ruby
require "objspace"
1000.times do
ObjectSpace.trace_object_allocations do
r = Ractor.new do
_obj = 'a' * 1024
end
r.join
end
end
```
$ untilfail lldb -b ./exe/ruby -o "target create ./exe/ruby" -o "run test.rb" -o continue
It would fail at `ractor_port_mark`, rp->r was a garbage value. Credit to John for finding the
solution.
Co-authored-by: John Hawthorn <john.hawthorn@shopify.com>
|
|
It crashes frequently on CI but I am not able to reproduce locally:
https://ci.rvm.jp/results/trunk-random1@ruby-sp2-noble-docker/5954509
https://ci.rvm.jp/results/trunk-random0@ruby-sp2-noble-docker/5954501
|
|
* 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
Notes:
Merged: https://github.com/ruby/ruby/pull/13445
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/13350
|
|
The table is global so accesses must be synchronized.
Notes:
Merged: https://github.com/ruby/ruby/pull/13349
|
|
|
|
When a Ractor is created whilst a tracepoint for
RUBY_INTERNAL_EVENT_NEWOBJ is active, the interpreter crashes. This is
because during the early setup of the Ractor, the stdio objects are
created, which allocates Ruby objects, which fires the tracepoint.
However, the tracepoint machinery tries to dereference the control frame
(ec->cfp->pc), which isn't set up yet and so crashes with a null pointer
dereference.
Fix this by not firing GC tracepoints if cfp isn't yet set up.
Notes:
Merged: https://github.com/ruby/ruby/pull/5990
|