[#100689] [Ruby master Feature#17303] Make webrick to bundled gems or remove from stdlib — hsbt@...

Issue #17303 has been reported by hsbt (Hiroshi SHIBATA).

11 messages 2020/11/02

[#100715] [Ruby master Bug#17306] TestGCCompact#test_ast_compacts test failures — v.ondruch@...

Issue #17306 has been reported by vo.x (Vit Ondruch).

11 messages 2020/11/05

[#100720] [Ruby master Feature#17307] A way to mark C extensions as thread-safe, Ractor-safe, or unsafe — eregontp@...

Issue #17307 has been reported by Eregon (Benoit Daloze).

22 messages 2020/11/05

[#100744] [Ruby master Bug#17310] Closed ractors should die — marcandre-ruby-core@...

Issue #17310 has been reported by marcandre (Marc-Andre Lafortune).

12 messages 2020/11/08

[#100753] [Ruby master Feature#17312] New methods in Enumerable and Enumerator::Lazy: flatten, product, compact — zverok.offline@...

Issue #17312 has been reported by zverok (Victor Shepelev).

11 messages 2020/11/09

[#100763] [Ruby master Feature#17314] Provide a way to declare visibility of attributes defined by attr* methods in a single expression — radek.bulat@...

SXNzdWUgIzE3MzE0IGhhcyBiZWVuIHJlcG9ydGVkIGJ5IHJhZGFyZWsgKFJhZG9zxYJhdyBCdcWC

17 messages 2020/11/10

[#100777] [Ruby master Feature#17316] On memoization — sawadatsuyoshi@...

Issue #17316 has been reported by sawa (Tsuyoshi Sawada).

18 messages 2020/11/11

[#100788] [Ruby master Misc#17319] Rename Random::urandom to os_random and document random data sources — zofrex@...

Issue #17319 has been reported by zofrex (James Sanderson).

11 messages 2020/11/11

[#100807] [Ruby master Feature#17322] Deprecate `Random::DEFAULT` and introduce `Random.default()` method to provide Ractor-supported default random generator — ko1@...

Issue #17322 has been reported by ko1 (Koichi Sasada).

14 messages 2020/11/12

[#100816] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage — ko1@...

Issue #17323 has been reported by ko1 (Koichi Sasada).

19 messages 2020/11/12

[#100849] [Ruby master Feature#17325] Adds Fiber#cancel, which forces a Fiber to break/return — nicholas.evans@...

Issue #17325 has been reported by nevans (Nicholas Evans).

17 messages 2020/11/14

[#100852] [Ruby master Feature#17326] Add Kernel#must! to the standard library — zimmerman.jake@...

SXNzdWUgIzE3MzI2IGhhcyBiZWVuIHJlcG9ydGVkIGJ5IGpleiAoSmFrZSBaaW1tZXJtYW4pLg0K

24 messages 2020/11/14

[#100858] [Ruby master Feature#17327] The Queue constructor should take an initial set of items — chris@...

Issue #17327 has been reported by chrisseaton (Chris Seaton).

10 messages 2020/11/15

[#100897] [Ruby master Feature#17330] Object#non — zverok.offline@...

Issue #17330 has been reported by zverok (Victor Shepelev).

21 messages 2020/11/17

[#100925] [Ruby master Feature#17331] Let Fiber#raise work with transferring fibers — nicholas.evans@...

Issue #17331 has been reported by nevans (Nicholas Evans).

12 messages 2020/11/18

[#100930] [Ruby master Feature#17333] Enumerable#many? — masafumi.o1988@...

Issue #17333 has been reported by okuramasafumi (Masafumi OKURA).

10 messages 2020/11/18

[#100971] [Ruby master Bug#17337] Don't embed Ruby build time configuration into Ruby — v.ondruch@...

Issue #17337 has been reported by vo.x (Vit Ondruch).

16 messages 2020/11/20

[#100999] [Ruby master Feature#17339] Semantic grouping on BigDecimal#to_s — co.chuma@...

Issue #17339 has been reported by chumaltd (Takahiro Chuma).

9 messages 2020/11/21

[#101071] [Ruby master Feature#17342] Hash#fetch_set — hunter_spawn@...

Issue #17342 has been reported by MaxLap (Maxime Lapointe).

26 messages 2020/11/25

[#101093] [Ruby master Misc#17346] DevelopersMeeting20201210Japan — mame@...

Issue #17346 has been reported by mame (Yusuke Endoh).

17 messages 2020/11/26

[#101141] [Ruby master Bug#17354] Module#const_source_location is misleading for constants awaiting autoload — tom@...

SXNzdWUgIzE3MzU0IGhhcyBiZWVuIHJlcG9ydGVkIGJ5IHRvbXN0dWFydCAoVG9tIFN0dWFydCku

21 messages 2020/11/29

[#101143] [Ruby master Feature#17355] Or-patterns (pattern matching like Foo(x) | Bar(x)) — fg@...

Issue #17355 has been reported by decuplet (Nikita Shilnikov).

8 messages 2020/11/29

[#101153] [Ruby master Feature#17356] Alignment of memory allocated through Fiddle struct's malloc — andrea.ribuoli@...

Issue #17356 has been reported by AndreaRibuoli (Andrea Ribuoli).

8 messages 2020/11/30

[ruby-core:101149] [Ruby master Feature#17307] A way to mark C extensions as thread-safe, Ractor-safe, or unsafe

From: shyouhei@...
Date: 2020-11-30 03:23:16 UTC
List: ruby-core #101149
Issue #17307 has been updated by shyouhei (Shyouhei Urabe).


Eregon (Benoit Daloze) wrote in #note-17:
> shyouhei (Shyouhei Urabe) wrote in #note-16:
> > This is not what I know is a thread-safety.  I understand what you need, but you should name the property differently than thread-safe, like for instance Truffle safe.
> 
> Could you explain what differs or what is your definition of thread safety?

For instance:

```C
#include <string.h>

const char *
foo(int bar)
{
    return strerror(bar);
}
```

This is not a thread-safe function.  `strerror(3)` is one of those functions which POSIX explicitly specifies to be thread-unsafe (IEEE Std 1003.1 Chapter 2).  Now, depending on operating systems this could in fact run in a thread-safe manner.  I guess musl libc could be one of such implementation that has reentrancy.  That is of course a very god property per-se, but doesn't mean the `foo` above can be considered thread-safe.  In fact it isn't on, for instance, OpenBSD.

Same discussion must apply when we replace that `strerror` into `NUM2CHR`.

> I guess it's something like "sufficient synchronization around shared mutable state + every function called is thread-safe or synchronized by all callers"?

A C function must be threa-safe as a whole.  If a C function calls something thread-unsafe it must not be thread-safe itself.  POSIX defines Thread-Safe to be "a thread-safe function can be safely invoked concurrently with other calls to the same function, or with calls to any other thread-safe functions, by multiple threads" (IEEE Std 1003.1 Chapter 3).  It doesn't allow a part of C function be unsafe due to it is call(s) to external function(s).

> When calling, e.g., libc functions, one needs to consult the man page for thread-safety.
> Similarly, when looking at rb_* functions, one needs to look the documentation of the Ruby implementation for whether these functions are thread-safe.
> That's how I see it.

I'm concerning about annotating a 3rd party C extension to be thread safe.  When a manual or document or something states that a function is thread safe, I guess nobody would look into its implementation to see if it contains call to problematic libc routines.

> And again, such a definition is not specific to TruffleRuby, it could apply to any Ruby implementation with parallel threads and C extension support, such as Rubinius and maybe others in the future.

OK, I was wrong about calling this TruffleRuby specific.  My concern is about portability.

> Maybe we can use another term, something like "parallel safe", but in the end the necessary condition is that calling the C extensions functions in parallel is correct, i.e., that these functions are thread-safe, assuming the `rb_*`, libc, etc, functions behave thread-safe as documented in their respective documentation.
> I get that it's a bit weird to mark a C extension as thread-safe, given that on CRuby they can't be executed in parallel just with that condition.
>
> But, on CRuby rb_* functions must be called under the GIL so rb_* are thread-safe on CRuby when used correctly (under the GIL).
> I think that makes thread-safe the most appropriate term for it.

This means everything that an extension library could call to be thread-safe at once (hence no lock needed), or to be thread-unsafe at all (hence need lock everywhere).  I guess it prevents gradual evolution of the implementation: when a part of our CAPI were made thread safe, but something remains unsafe,  There is no way to express that info because everything are already marked safe.  Effectively results in no thread safety at all is the easiest solution for us.  I don't think that is a good future.

----------------------------------------
Feature #17307: A way to mark C extensions as thread-safe, Ractor-safe, or unsafe
https://bugs.ruby-lang.org/issues/17307#change-88834

* Author: Eregon (Benoit Daloze)
* Status: Open
* Priority: Normal
----------------------------------------
I would like to design a way to mark C extensions as thread-safe, Ractor-safe, or unsafe (= needs process-global lock).
By default, if not marked, C extensions would be treated as unsafe for compatibility.

Specifically, TruffleRuby supports C extensions, but for scalability it is important to run at least some of them in parallel (e.g., HTTP parsing in Puma).
This was notably mentioned in my [RubyKaigi talk](https://speakerdeck.com/eregon/running-rack-and-rails-faster-with-truffleruby?slide=17).
TruffleRuby defaults to acquire a global lock when executing C extension code for maximum compatibility (Ruby code OTOH can always run in parallel).
There is a command-line option for that lock and it can be disabled, but then it is disabled for all C extensions.
The important property for TruffleRuby is that the C extension does not need a global lock, i.e., that it synchronizes any mutable state in C that could be accessed by multiple threads, such as global C variables.
I believe many C extensions are already thread-safe, or can easily become thread-safe, because they do not rely on global state and do not share the RData objects between threads.

Ractor also needs a way to mark C extensions, to know if it's OK to use the C extension in multiple Ractors in parallel, and that the C extension will not leak non-shareable objects from one Ractor to another, which would lead to bugs & segfaults.
Otherwise, C extensions could only be used on the main/initial Ractor (or need to acquire a process-global lock whenever executing C extension code and ensure no non-shareable objects leak between Ractors), which would be a very big limitation (almost every non-trivial application depends on a C extension transitively).

In both cases, global state in the C extension needs synchronization.
In the thread-safe case, mutable state in C that could be accessed by multiple Ruby threads needs to be synchronized too (there might be no such state, e.g., if C extension objects are created per Thread).
In the Ractor case, the C extension must never pass an object from a Ractor to another, unless it is a shareable object.

What do you think would be a good way to "mark" C extensions?
Maybe defining a symbol in the C extension, similar to the `Init_foo` we have, like say `foo_is_thread_safe`/`foo_is_ractor_safe`?
A symbol including the C extension name seems best, to avoid any possible confusion when looking it up.

Maybe there are other ways to mark C extensions than defining symbols, that could still be read by the Ruby implementation reliably?

I used the term `C extensions` but of course it would apply to native extensions too (including C++/Rust/...).

cc @ko1



-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>

In This Thread