[#106939] [Ruby master Bug#18455] `IO#close` has poor performance and difficult to understand semantics. — "ioquatix (Samuel Williams)" <noreply@...>

Issue #18455 has been reported by ioquatix (Samuel Williams).

10 messages 2022/01/01

[#106977] [Ruby master Feature#18461] closures are capturing unused variables — "bughit (bug hit)" <noreply@...>

Issue #18461 has been reported by bughit (bug hit).

12 messages 2022/01/05

[#106994] [Ruby master Feature#18462] Proposal to merge WASI based WebAssembly support — "katei (Yuta Saito)" <noreply@...>

Issue #18462 has been reported by katei (Yuta Saito).

8 messages 2022/01/07

[#106996] [Ruby master Feature#18463] Random number generation with xoshiro — "bbrklm (Benson Muite)" <noreply@...>

Issue #18463 has been reported by bbrklm (Benson Muite).

8 messages 2022/01/07

[#107005] [Ruby master Bug#18464] RUBY_INTERNAL_EVENT_NEWOBJ tracepoint causes an interpreter crash when combined with Ractors — "kjtsanaktsidis (KJ Tsanaktsidis)" <noreply@...>

Issue #18464 has been reported by kjtsanaktsidis (KJ Tsanaktsidis).

14 messages 2022/01/08

[#107008] [Ruby master Bug#18465] Make `IO#write` atomic. — "ioquatix (Samuel Williams)" <noreply@...>

Issue #18465 has been reported by ioquatix (Samuel Williams).

16 messages 2022/01/09

[#107073] [Ruby master Feature#18481] Porting YJIT to Rust (request for feedback) — "maximecb (Maxime Chevalier-Boisvert)" <noreply@...>

Issue #18481 has been reported by maximecb (Maxime Chevalier-Boisvert).

26 messages 2022/01/12

[#107106] [Ruby master Bug#18487] Kernel#binding behaves differently depending on implementation language of items on the stack — "alanwu (Alan Wu)" <noreply@...>

Issue #18487 has been reported by alanwu (Alan Wu).

11 messages 2022/01/13

[#107190] [Ruby master Feature#18498] Introduce a public WeakKeysMap that compares by equality — "byroot (Jean Boussier)" <noreply@...>

Issue #18498 has been reported by byroot (Jean Boussier).

17 messages 2022/01/19

[#107203] [Ruby master Bug#18501] [BUG] try to mark T_NONE object in RubyVM::InstructionSequence. load_from_binary — "byroot (Jean Boussier)" <noreply@...>

Issue #18501 has been reported by byroot (Jean Boussier).

8 messages 2022/01/20

[#107204] [Ruby master Bug#18502] Make ruby-2.7.5 on Solaris 10 ld.so.1: gcc: fatal: libintl.so.8: open failed: No such file or directory — "dklein (Dmitri Klein)" <noreply@...>

Issue #18502 has been reported by dklein (Dmitri Klein).

8 messages 2022/01/20

[#107275] [Ruby master Bug#18512] MacOS 12.1 Monterey Bug — "oucl5976@... (Paul Liu)" <noreply@...>

Issue #18512 has been reported by oucl5976@gmail.com (Paul Liu).

9 messages 2022/01/25

[#107291] [Ruby master Bug#18518] NoMemoryError + [FATAL] failed to allocate memory for twice 1 << large — "Eregon (Benoit Daloze)" <noreply@...>

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

12 messages 2022/01/26

[#107310] [Ruby master Bug#18555] Running "bundle exec middleman server" on M1 Mac gives [BUG] Bus Error at 0x0000000104b04000 — "anthonyaykut (Anthony Aykut)" <noreply@...>

Issue #18555 has been reported by anthonyaykut (Anthony Aykut).

13 messages 2022/01/28

[#107346] [Ruby master Misc#18557] DevMeeting-2022-02-17 — "mame (Yusuke Endoh)" <noreply@...>

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

18 messages 2022/01/29

[#107392] [Ruby master Bug#18560] "Compaction isn't available on this platform" error running PG test suite on ppc64le — "vo.x (Vit Ondruch)" <noreply@...>

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

7 messages 2022/01/31

[ruby-core:107019] [Ruby master Bug#18465] Make `IO#write` atomic.

From: "ioquatix (Samuel Williams)" <noreply@...>
Date: 2022-01-09 20:19:50 UTC
List: ruby-core #107019
Issue #18465 has been updated by ioquatix (Samuel Williams).


> I think it'd better to guarantee atomicity for puts and write, even if the same fd is used by multiple IO instances, and even if the same fd is used by multiple processes.

The current implementation before and after this PR makes no such guarantee unfortunately. The best you can do as a user is buffer your own string and call write with that as an argument to get any kind of atomic behaviour, but that only applies to non-sync IOs.

> The write lock does not address both of these cases and it's then leaking implementation details (e.g., other Rubies might not have a write lock).

The write lock internally protects `sync=true` IO which has an internal per-IO buffer. All I've done in my PR is perform the lock once per operation rather than once per system call, so I've moved the lock "up" a little bit to reduce the number of times it would be invoked and increase the amount of synchronisation so that IOs can't interrupt each other.

> This is what TruffleRuby does, and it's fully portable.

https://github.com/oracle/truffleruby/blob/bd36e75003a1f2d57dbc947350cb076e9a827cbd/src/main/ruby/truffleruby/core/io.rb#L2375-L2394

How is sync handled? I don't see the internal buffer is used in `def write`.

> Ah and in either case the IO scheduler should either receive the already-concatenated string, or all strings to write together in a single hook call.
Calling the write hook for each argument is of course broken.

The interface for IO#write has to deal with both buffered and un-buffered operations and so we hooked into the internal read and write functions of IO. The best we can hope for is to tidy up how they are used. We don't provide a strong guarantee between one call to `IO#write` corresponding to one call to `Scheduler#io_write`... while it's true in most cases, it's not true in all cases. This is really just an artefact of the complexity of the current implementation in `io.c`.

----------------------------------------
Bug #18465: Make `IO#write` atomic.
https://bugs.ruby-lang.org/issues/18465#change-95853

* Author: ioquatix (Samuel Williams)
* Status: Open
* Priority: Normal
* Assignee: ioquatix (Samuel Williams)
* Backport: 2.6: UNKNOWN, 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN
----------------------------------------
Right now, `IO#write` including everything that calls it including `IO#puts`, has a poorly specified behaviour w.r.t. other fibers/threads that call `IO#write` at the same time.

Internally, we have a write lock, however it's only used to lock against individual writes rather than the whole operation. From a user point of view, there is some kind of atomicity, but it's not clearly defined and depends on many factors, e.g. whether `write` or `writev` is used internally.

We propose to make `IO#write` an atomic operation, that is, `IO#write` on a synchronous/buffered IO will always perform the write operation using a lock around the entire operation.

In theory, this should actually be more efficient than the current approach which may acquire and release the lock several times per operation, however in practice I'm sure it's almost unnoticeable.

Where it does matter, is when interleaved operations invoke the fiber scheduler. By using a single lock around the entire operation, rather than one or more locks around the system calls, the entire operation is more predictable and behaves more robustly.



-- 
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