| Age | Commit message (Collapse) | Author |
|
These tests use NM threads but NT is not freed for MN thread, causing it
to be reported as memory leaks in LSAN. For example:
#1 0x62ee7bc67e99 in calloc1 gc/default/default.c:1495:12
#2 0x62ee7bc7ba00 in rb_gc_impl_calloc gc/default/default.c:8216:5
#3 0x62ee7bc631d1 in ruby_xcalloc_body gc.c:5221:12
#4 0x62ee7bc5cdbc in ruby_xcalloc gc.c:5215:34
#5 0x62ee7bdea4c6 in native_thread_alloc thread_pthread.c:2187:35
#6 0x62ee7bdec31b in native_thread_check_and_create_shared thread_pthread_mn.c:429:39
#7 0x62ee7bdea484 in native_thread_create_shared thread_pthread_mn.c:531:12
#8 0x62ee7bdea1da in native_thread_create thread_pthread.c:2403:16
#9 0x62ee7bdde2eb in thread_create_core thread.c:884:11
#10 0x62ee7bde4466 in thread_initialize thread.c:992:16
|
|
* 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
|
|
(#12996)
TestThreadInstrumentation#test_sleeping_inside_ractor is a flaky and failing intermittently. Additionally, Launchable reported this test as a top flaky test. (Link: https://app.launchableinc.com/organizations/ruby/workspaces/ruby/insights/unhealthy-tests)
It failed only failed intermittently on ModGC workflow, so I'm gonna skip this test on ModGC workflow.
Notes:
Merged-By: ono-max <onoto1998@gmail.com>
|
|
The test meant to assert the thread is suspended at least once,
but was actually asserting to it to be suspected at least twice.
|
|
Introduce `rb_thread_lock_native_thread()` to allocate dedicated
native thread to the current Ruby thread for M:N threads.
This C API is similar to Go's `runtime.LockOSThread()`.
Accepted at https://github.com/ruby/dev-meeting-log/blob/master/2023/DevMeeting-2023-08-24.md
(and missed to implement on Ruby 3.3.0)
|
|
... to disable a warning: assigned but unused variable - expected
|
|
It seems that the Ractor sleep GVL event arrives very slightly after the
value becomes available and other threads wake (which makes sense) so we
need a little additional time to ensure we end up in a consisteny state.
|
|
|
|
This reverts commit ad54fbf281ca1935e79f4df1460b0106ba76761e.
|
|
[Bug #20019]
This fixes GVL instrumentation in three locations it was missing:
- Suspending when blocking on a Ractor
- Suspending when doing a coroutine transfer from an M:N thread
- Resuming after an M:N thread starts
Co-authored-by: Matthew Draper <matthew@trebex.net>
|
|
Followup: https://github.com/ruby/ruby/pull/9029
[Bug #20019]
Some events still weren't triggered from the right place.
The test suite was also improved a bit more.
|
|
This entirely changes how it is tested. Rather than to use counters
we now record the timeline of events with associated threads which
makes it much easier to assert that certains events are only preceded
by a specific event, and makes it much easier to debug unexpected
timelines.
Co-Authored-By: Étienne Barrié <etienne.barrie@gmail.com>
Co-Authored-By: JP Camara <jp@jpcamara.com>
Co-Authored-By: John Hawthorn <john@hawthorn.email>
|
|
Context: https://github.com/ivoanjo/gvl-tracing/pull/4
Some hooks may want to collect data on a per thread basis.
Right now the only way to identify the concerned thread is to
use `rb_nativethread_self()` or similar, but even then because
of the thread cache or MaNy, two distinct Ruby threads may report
the same native thread id.
By passing `thread->self`, hooks can use it as a key to store
the metadata.
NB: Most hooks are executed outside the GVL, so such data collection
need to use a thread-safe data-structure, and shouldn't use the
reference in other ways from inside the hook.
They must also either pin that value or handle compaction.
|
|
It's very flaky for some unknown reason. Something we have
an extra EXITED event. I suspect some other test is causing this.
Notes:
Merged: https://github.com/ruby/ruby/pull/6133
|
|
We saw the following failure:
```
TestThreadInstrumentation#test_thread_instrumentation [/tmp/ruby/v3/src/trunk-random3/test/-ext-/thread/test_instrumentation_api.rb:25]:
Expected 0..3 to include 4.
```
Which shouldn't happen unless somehow there was a leaked thread.
Notes:
Merged: https://github.com/ruby/ruby/pull/6128
|
|
* Extracted some assertions.
* Assert counter values should be positive.
Notes:
Merged: https://github.com/ruby/ruby/pull/6111
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/6111
|
|
Recently `TestThreadInstrumentation#test_join_counters` often fails as
```
<[1, 1, 1]> expected but was
<[2, 2, 2]>.
```
Probably it seems that the thread is suspended more than once.
There may be no guarantee that the subject thread never be suspended
more than once.
|
|
[Bug #18900]
Thread#join and a few other codepaths are using native sleep as
a way to suspend the current thread. So we should call the relevant
hook when this happen, otherwise some thread may transition
directly from `RESUMED` to `READY`.
Notes:
Merged: https://github.com/ruby/ruby/pull/6101
|
|
I suspect that sometimes on CI the last thread is prempted before eaching the exit hook
causing the test to flake. I can't find a good way to force it to run.
|
|
|
|
It previously failed with:
```
1) Failure:
TestThreadInstrumentation#test_thread_instrumentation_fork_safe [/home/runner/work/ruby/ruby/src/test/-ext-/thread/test_instrumentation_api.rb:50]:
<5> expected but was
<4>.
```
Suggesting one `EXIT` event wasn't fired or processed.
Adding an assetion on `Thead#status` may help figure out what is wrong.
Notes:
Merged: https://github.com/ruby/ruby/pull/6032
|
|
[Feature #18339]
After experimenting with the initial version of the API I figured there is a need
for an exit event to cleanup instrumentation data. e.g. if you record data in a
{thread_id -> data} table, you need to free associated data when a thread goes away.
Notes:
Merged: https://github.com/ruby/ruby/pull/6029
|
|
`test_thread_instrumentation_fork_safe` has been failing occasionaly
on Ubuntu and Arch. At this stage we're not sure why, all we know is
that the child exit with status 1.
I suspect that something entirely unrelated cause the forked children
to fail on exit, so by using `exit!(0)` and doing assertions in the
parent I hope to be resilient to that.
Notes:
Merged: https://github.com/ruby/ruby/pull/5983
|
|
The tests fail randomly on some platforms.
http://rubyci.s3.amazonaws.com/ubuntu/ruby-master/log/20220605T213004Z.fail.html.gz
http://rubyci.s3.amazonaws.com/arch/ruby-master/log/20220605T210003Z.fail.html.gz
```
[15737/21701] TestThreadInstrumentation#test_thread_instrumentation_fork_safe/home/chkbuild/chkbuild/tmp/build/20220605T213004Z/ruby/tool/lib/test/unit/assertions.rb:109:in `assert': Expected 0 to be nonzero?. (Test::Unit::AssertionFailedError)
```
The failures seem to depend on context switches. I suspect `sleep 0.05`
is too short, so this change tries to extend the wait time.
|
|
Ref: https://bugs.ruby-lang.org/issues/18339
Design:
- This tries to minimize the overhead when no hook is registered.
It should only incur an extra unsynchronized boolean check.
- The hook list is protected with a read-write lock as to cause
contention when some hooks are registered.
- The hooks MUST be thread safe, and MUST NOT call into Ruby as they
are executed outside the GVL.
- It's simply a noop on Windows.
API:
```
rb_internal_thread_event_hook_t * rb_internal_thread_add_event_hook(rb_internal_thread_event_callback callback, rb_event_flag_t internal_event, void *user_data);
bool rb_internal_thread_remove_event_hook(rb_internal_thread_event_hook_t * hook);
```
You can subscribe to 3 events:
- READY: called right before attempting to acquire the GVL
- RESUMED: called right after successfully acquiring the GVL
- SUSPENDED: called right after releasing the GVL.
The hooks MUST be threadsafe, as they are executed outside of the GVL, they also MUST NOT call any Ruby API.
Notes:
Merged: https://github.com/ruby/ruby/pull/5500
|