Граф коммитов

68 Коммитов

Автор SHA1 Сообщение Дата
Nobuyoshi Nakada 334b69e504 rb_id_serial_to_id: return unregistered ID as an internal ID
```ruby
def foo(*); ->{ super }; end
```

This code makes anonymous parameters which is not registered as an
ID.  The problem is that when Ractors try to scan `getlocal`
instructions, it puts the Symbol corresponding to the parameter
in to a hash.  Since it is not registered, we end up with a
strange exception.  This commit wraps the unregistered ID in an
internal ID so that we get the same exception for `...` as `*`.

Co-Authored-By: Aaron Patterson <tenderlove@ruby-lang.org>
Co-Authored-By: John Hawthorn <john@hawthorn.email>
2021-11-07 12:40:27 +09:00
Satoshi Moris Tagomori 489e5e3a82 the core problem is the Proc is not shareable 2021-10-27 16:13:43 +09:00
Koichi Sasada acb23454e5 allow to access ivars of classes/modules
if an ivar of a class/module refer to a shareable object, this ivar
can be read from non-main Ractors.
2021-10-23 01:32:55 +09:00
Alan Wu 7622819147
Fix Ractor.make_shareable changing locals for Procs
env_copy() uses rb_ary_delete_at() with a loop counting up while
iterating through the list of read only locals. rb_ary_delete_at() can
shift elements in the array to an index lesser than the loop index,
causing locals to be missed and set to Qfalse in the returned
environment.

Iterate through the locals in reverse instead, this way the shifting
never happens for locals that are yet to be visited and we process all
the locals in the array.

[Bug #18023]
2021-10-06 15:38:33 -04:00
Peter Zhu bbedd29b6e [Bug #18117] Fix Ractor race condition with GC
rb_objspace_reachable_objects_from requires that the GC not be active.
Since the Ractor barrier is not executed for incremental sweeping,
Ractor may call rb_objspace_reachable_objects_from after sweeping
has started to share objects. This causes a crash that looks like
the following:

```
<internal:ractor>:627: [BUG] rb_objspace_reachable_objects_from() is not supported while during_gc == true
```

Co-authored-by: Vinicius Stock <vinicius.stock@shopify.com>
2021-08-24 09:47:42 -04:00
Nobuyoshi Nakada 9eae8cdefb
Prefer qualified names under Thread 2021-06-29 11:41:10 +09:00
eileencodes 8209b73580 Evacuate transient heap when enabling ractors
If the GC has been disabled we need to re-enable it so we can evacuate
the transient heap.

Fixes https://bugs.ruby-lang.org/issues/17985

[Bug #17985] [ruby-core:104260]

Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org>
2021-06-23 10:03:09 -07:00
Jun Aruga 9e56a22be6 bootstraptest/test_ractor.rb: Skip an assertion on Travis arm64.
Skip the assertion to test the `Ractor.select` from multiple ractors that rarely
fails on Travis arm64.
See <https://bugs.ruby-lang.org/issues/17878>.
2021-05-25 12:38:05 +02:00
Nobuyoshi Nakada b3c53a8a88
Make Ractor stdio belonging to the Ractor [Bug #17672]
Defer making ractor stdio until ractor started.
Before ractor started, created objects belong to the caller ractor
instead of the created ractor.
2021-03-07 00:58:28 +09:00
Koichi Sasada 7b9476fbfa Ractor.allocate should not be allowed
Ractor.allocate and Ractor#dup should not be allowed like Thread.
[Bug #17642]
2021-02-18 22:35:34 +09:00
Nobuyoshi Nakada 3acc81d9e4 Fixed race in dtoa [Bug #17612]
Fixed the race condition when replacing `freelist` entry with its
chained next element.  At acquiring an entry, hold the entry once
with the special value, then release by replacing it with the next
element again after acquired.  If another thread is holding the
same entry at that time, spinning until the entry gets released.

Co-Authored-By: Koichi Sasada <ko1@atdot.net>
2021-02-10 19:44:47 +09:00
Nobuyoshi Nakada 1cdae49d39 Implement NameError::message#clone for Ractor 2021-02-01 19:54:21 +09:00
Koichi Sasada fff1edf23b fix Ractor.yield(obj, move: true)
Ractor.yield(obj, move: true) and
Ractor.select(..., yield_value: obj, move: true) tried to yield a
value with move semantices, but if the trial is faild, the obj
should not become a moved object.

To keep this rule, `wait_moving` wait status is introduced.

New yield/take process:
(1) If a ractor tried to yield (move:true), make taking racotr's
    wait status `wait_moving` and make a moved object by
    `ractor_move(obj)` and wakeup taking ractor.
(2) If a ractor tried to take a message from a ractor waiting fo
    yielding (move:true), wakeup the ractor and wait for (1).
2021-01-22 12:16:37 +09:00
Koichi Sasada e7fc353f04 enable constant cache on ractors
constant cache `IC` is accessed by non-atomic manner and there are
thread-safety issues, so Ruby 3.0 disables to use const cache on
non-main ractors.

This patch enables it by introducing `imemo_constcache` and allocates
it by every re-fill of const cache like `imemo_callcache`.
[Bug #17510]

Now `IC` only has one entry `IC::entry` and it points to
`iseq_inline_constant_cache_entry`, managed by T_IMEMO object.

`IC` is atomic data structure so `rb_mjit_before_vm_ic_update()` and
`rb_mjit_after_vm_ic_update()` is not needed.
2021-01-05 02:27:58 +09:00
Koichi Sasada d0e4ccbefc add Ractor.main
It returns main Ractor, like Thread.main.
[Feature #17418]
2020-12-22 05:54:14 +09:00
Koichi Sasada 35471a9487 add Ractor#[]/#[]= for ractor local storage
This API is similar to plain old Thread#[]/Fiber#[] interface
with symbol key.
2020-12-22 05:26:32 +09:00
Koichi Sasada a2950369bd TracePoint.new(&block) should be ractor-local
TracePoint should be ractor-local because the Proc can violate the
Ractor-safe.
2020-12-22 00:03:00 +09:00
Koichi Sasada 730f314171 fix Ractor.make_shareable() with Class/Module
To check shareable-ness, rb_ractor_shareable_p() is needed
for Class/Module objects isntead of checking flags.
2020-12-21 01:13:39 +09:00
Koichi Sasada 80cb9165fa add "copy: true" option for Ractor.make_shareable
Ractor.make_shareable(obj) tries to make obj a shareable object
by changing the attribute of obj and traversable objects from obj
(mainly freeze them).

"copy: true" option is more conservative approach by make deep
copied object and make it sharable. It doesn't affect any existing
objects.
2020-12-19 05:52:18 +09:00
Nobuyoshi Nakada 359ad4423e
strip trailing spaces [ci skip] 2020-12-16 20:33:31 +09:00
Koichi Sasada a9a7f4d8b8 Ractor#receive_if to receive only matched messages
Instead of Ractor.receive, Ractor.receive_if can provide a pattern
by a block and you can choose the receiving message.

[Feature #17378]
2020-12-16 19:12:48 +09:00
Koichi Sasada 70a311fdeb trap on non-main ractor
trap can accept blopck/Proc and it can violate Rator isolation,
so the Proc should be isolatable when trap is used on non-main ractor.
2020-12-12 08:36:52 +09:00
Koichi Sasada d741c77b5f fix ivar with shareable objects issue
Instance variables of sharable objects are accessible only from
main ractor, so we need to check it correctly.
2020-12-12 06:19:18 +09:00
Koichi Sasada 72f1c43584 ObjectSpace._id2ref should not support unshareable
ObjectSpace._id2ref(id) can return any objects even if they are
unshareable, so this patch raises RangeError if it runs on multi-ractor
mode and the found object is unshareable.
2020-12-10 18:27:44 +09:00
Marc-Andre Lafortune 27b6df9653 Add test that `Ractor.make_shareable` calls user defined `#freeze` 2020-12-08 17:49:14 -05:00
Marc-Andre Lafortune 53ce71b5af Ractor.select requires an argument or yield_value 2020-12-07 02:21:12 -05:00
Koichi Sasada c2fa024e02 fix Thread's interrupt and Ractor#take issue
Thread's interrupt set Ractor's wakeup_status as interrupted, but
the status remains next Ractor communication API. This patch makes
to ignore the previous interrupt state.
[Bug #17366]

Also this patch solves the Thread#kill and Ractor#take issues.
2020-12-07 16:01:35 +09:00
Koichi Sasada 764de7566f should not use rb_str_modify(), too
Same as 8247b8edde, should not use rb_str_modify() here.

https://bugs.ruby-lang.org/issues/17343#change-88858
2020-12-01 18:16:23 +09:00
Koichi Sasada 8247b8edde should not use rb_ary_modify()
ractor_copy() used rb_ary_modify() to make sure this array is not
sharing anything, but it also checks frozen flag. So frozen arrays
raises an error. To solve this issue, this patch introduces new
function rb_ary_cancel_sharing() which makes sure the array does not
share another array and it doesn't check frozen flag.
[Bug #17343]

A test is quoted from https://github.com/ruby/ruby/pull/3817
2020-12-01 13:18:32 +09:00
Marc-Andre Lafortune e25165b3fc Fix `Ractor.make_shareable` for recursive structures with unfreezable components
Followup to #3823
2020-11-30 19:33:37 -05:00
Nobuyoshi Nakada 930a135524
Fixed Ractor.shareable? on cross-recursive objects [Bug #17344] 2020-11-30 16:07:36 +09:00
Takashi Kokubun eaa87be5f6
Skip test_ractor.rb:137 for --jit-min-calls=5
It's failing like
http://ci.rvm.jp/results/trunk-mjit-wait@phosphorus-docker/3270373 but I
have no bandwidth to fix it for now.

We're still checking --jit-wait (without --jit-min-calls=5) on GitHub
Actions.
2020-11-24 20:18:05 -08:00
Takashi Kokubun c6b7b4f6f4
Report a more detailed situation of test_ractor.rb:137
This test has been very unstable. I'd like to instantly know whether
it's always failing or random when I look at a CI failure output.
2020-11-24 19:50:42 -08:00
Koichi Sasada fa3670e6e4 remove Ractor#close
close_incoming by antoher ractor means there is no other messages
will be sent to the ractor, so Ractor.receive will block forever,
and it should raise and stop.

close_outgoing by antoher ractor means, ... I don't have good idea
to use it. It can be a private method.

Ractor#close calls both, but it does not make sense to call
different purpose methods, so I remove it.
2020-11-11 18:11:09 +09:00
Koichi Sasada deed21bb08 ignore yield_atexit if outgoing port is closed
If outgoing_port is closed, Ractor.yield never successes.
[Bug #17310]
2020-11-11 18:10:43 +09:00
Koichi Sasada db31ace934 Threads in a ractor will be killed with the ractor
If a terminating ractor has child threads, then kill all child
threads.
2020-11-11 15:49:02 +09:00
Koichi Sasada 5fefb53249 Copy for Ractor.send() without marshal.
Now copying objects do not need marshal protocol.
2020-11-02 03:31:58 +09:00
Koichi Sasada 89c8ca32d0 add a test of define_method with shareable Proc.
a method defined by define_method with normal Proc can not cross
ractors because the normal Proc is not shareable. However,
shareable Proc can be crossed between ractors, so the method with
shareable Proc should be called correctly.
2020-10-30 16:52:09 +09:00
Koichi Sasada 5d97bdc2dc Ractor.make_shareable(a_proc)
Ractor.make_shareable() supports Proc object if
(1) a Proc only read outer local variables (no assignments)
(2) read outer local variables are shareable.

Read local variables are stored in a snapshot, so after making
shareable Proc, any assignments are not affeect like that:

```ruby
a = 1
pr = Ractor.make_shareable(Proc.new{p a})
pr.call #=> 1
a = 2
pr.call #=> 1 # `a = 2` doesn't affect
```

[Feature #17284]
2020-10-30 03:12:09 +09:00
Marc-Andre Lafortune 9c8f0a34df Use 'shareable' with an 'e' [ci skip] 2020-10-25 18:10:14 -04:00
Marc-Andre Lafortune 5e6f9fd83a Tweak a few Ractor tests that were missing comments [ci skip] 2020-10-25 16:44:59 -04:00
Marc-Andre Lafortune ee54075a94 Remove trailing whitespace [ci skip] 2020-10-25 16:38:37 -04:00
Koichi Sasada 0c0d0752f1 allow to access ivars of frozen shareable objects
Accessing a shareable object is prohibitted because it can cause
race condition, but if the shareable object is frozen, there is no
problem to access ivars.
2020-10-22 00:43:44 +09:00
Koichi Sasada 2f50936cb9 Ractor.make_shareable(obj)
Introduce new method Ractor.make_shareable(obj) which tries to make
obj shareable object. Protocol is here.

(1) If obj is shareable, it is shareable.
(2) If obj is not a shareable object and if obj can be shareable
    object if it is frozen, then freeze obj. If obj has reachable
    objects (rs), do rs.each{|o| Ractor.make_shareable(o)}
    recursively (recursion is not Ruby-level, but C-level).
(3) Otherwise, raise Ractor::Error. Now T_DATA is not a shareable
    object even if the object is frozen.

If the method finished without error, given obj is marked as
a sharable object.

To allow makng a shareable frozen T_DATA object, then set
`RUBY_TYPED_FROZEN_SHAREABLE` as type->flags. On default,
this flag is not set. It means user defined T_DATA objects are
not allowed to become shareable objects when it is frozen.

You can make any object  shareable by setting FL_SHAREABLE flag,
so if you know that the T_DATA object is shareable (== thread-safe),
set this flag, at creation time for example. `Ractor` object is one
example, which is not a frozen, but a shareable object.
2020-10-21 07:59:24 +09:00
Koichi Sasada 512752ba19 fix condition 2020-10-20 23:48:20 +09:00
Koichi Sasada 67c25a34a7 skip `echo foo` on Solaris
On Solaris, it seems to access ENV in ``, so skip it now.

```
stderr output is not empty
   Exception `NameError' at bootstraptest.tmp.rb:7 - can not access non-sharable objects in constant Object::ENV by non-main Ractor.
   #<Thread:0x0044cdf0 run> terminated with exception (report_on_exception is true):
   bootstraptest.tmp.rb:7:in ``': can not access non-sharable objects in constant Object::ENV by non-main Ractor. (NameError)
   Exception `Ractor::RemoteError' at <internal:ractor>:130 - thrown by remote Ractor.
   <internal:ractor>:130:in `take': thrown by remote Ractor. (Ractor::RemoteError)
           from bootstraptest.tmp.rb:55:in `<main>'
   bootstraptest.tmp.rb:7:in ``': can not access non-sharable objects in constant Object::ENV by non-main Ractor. (NameError)
           from bootstraptest.tmp.rb:7:in `ractor_local_globals'
           from bootstraptest.tmp.rb:54:in `block in <main>'
```
2020-10-20 17:57:20 +09:00
Koichi Sasada ade411465d ObjectSpace.each_object with Ractors
Unshareable objects should not be touched from multiple ractors
so ObjectSpace.each_object should be restricted. On multi-ractor
mode, ObjectSpace.each_object only iterates shareable objects.
[Feature #17270]
2020-10-20 15:39:37 +09:00
Koichi Sasada 99310e3eb5 Some global variables can be accessed from ractors
Some global variables should be used from non-main Ractors.
[Bug #17268]

```ruby
     # ractor-local (derived from created ractor): debug
     '$DEBUG' => $DEBUG,
     '$-d' => $-d,

     # ractor-local (derived from created ractor): verbose
     '$VERBOSE' => $VERBOSE,
     '$-w' => $-w,
     '$-W' => $-W,
     '$-v' => $-v,

     # process-local (readonly): other commandline parameters
     '$-p' => $-p,
     '$-l' => $-l,
     '$-a' => $-a,

     # process-local (readonly): getpid
     '$$'  => $$,

     # thread local: process result
     '$?'  => $?,

     # scope local: match
     '$~'  => $~.inspect,
     '$&'  => $&,
     '$`'  => $`,
     '$\''  => $',
     '$+'  => $+,
     '$1'  => $1,

     # scope local: last line
     '$_' => $_,

     # scope local: last backtrace
     '$@' => $@,
     '$!' => $!,

     # ractor local: stdin, out, err
     '$stdin'  => $stdin.inspect,
     '$stdout' => $stdout.inspect,
     '$stderr' => $stderr.inspect,
```
2020-10-20 15:38:54 +09:00
Koichi Sasada fad97f1f96 sync generic_ivtbl
generic_ivtbl is a process global table to maintain instance variables
for non T_OBJECT/T_CLASS/... objects. So we need to protect them
for multi-Ractor exection.

Hint: we can make them Ractor local for unshareable objects, but
      now it is premature optimization.
2020-10-14 16:36:55 +09:00
Koichi Sasada 11c2f0f36c sync enc_table and rb_encoding_list
enc_table which manages Encoding information. rb_encoding_list
also manages Encoding objects. Both are accessed/modified by ractors
simultaneously so that they should be synchronized.

For enc_table, this patch introduced GLOBAL_ENC_TABLE_ENTER/LEAVE/EVAL
to access this table with VM lock. To make shortcut, three new global
variables global_enc_ascii, global_enc_utf_8, global_enc_us_ascii are
also introduced.

For rb_encoding_list, we split it to rb_default_encoding_list (256 entries)
and rb_additional_encoding_list. rb_default_encoding_list is fixed sized Array
so we don't need to synchronized (and most of apps only needs it). To manage
257 or more encoding objects, they are stored into rb_additional_encoding_list.
To access rb_additional_encoding_list., VM lock is needed.
2020-10-14 14:02:06 +09:00