From: "kjtsanaktsidis (KJ Tsanaktsidis) via ruby-core" <ruby-core@ml.ruby-lang.org>
To: ruby-core@ml.ruby-lang.org
Cc: "kjtsanaktsidis (KJ Tsanaktsidis)" <noreply@ruby-lang.org>
Subject: [ruby-core:116224] [Ruby master Bug#20169] `GC.compact` can raises `EFAULT` on IO
Date: Tue, 16 Jan 2024 09:34:42 +0000 (UTC) [thread overview]
Message-ID: <redmine.journal-106244.20240116093441.17@ruby-lang.org> (raw)
In-Reply-To: redmine.issue-20169.20240109103749.17@ruby-lang.org
Issue #20169 has been updated by kjtsanaktsidis (KJ Tsanaktsidis).
Thought: we could probably remove the need for the read barrier if we swept the heap, and _then_ compacted. So we wouldn't free any objects in between moving things and updating refs. It would mean scanning the first half of each heap twice (once to sweep it, and once again to find the holes to fill with compacted objects). But maybe `GC.compact` is not that performance sensitive since it’s mostly used before forking multiprocess web servers?
It would hurt perf for `GC.auto_compact`, but I don't really know if there's much to be done about it. I can't find any literature on conservative, incremental, moving GC's, which is what you'd want for `auto_compact`. Immix is conservative and moving, but it moves objects whilst stopping the world. Incremental or concurrent moving GC's like Shenandoah work by inserting compiler-provided read barriers around all accesses (which we can't do to C extensions) to fix up moved objects as they're loaded from the heap, and using compiler generated stackmaps (which we can't have for C extensions) to directly update existing moved references on the stack.
CC @eightbitraptor since I'm pretty sure I've heard you talk about immix before, maybe you have thoughts?
----------------------------------------
Bug #20169: `GC.compact` can raises `EFAULT` on IO
https://bugs.ruby-lang.org/issues/20169#change-106244
* Author: ko1 (Koichi Sasada)
* Status: Open
* Priority: Normal
* Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN
----------------------------------------
1. `GC.compact` introduces read barriers to detect read accesses to the pages.
2. I/O operations release GVL to pass the control while their execution, and another thread can call `GC.compact` (or auto compact feature I guess, but not checked yet).
3. Call `write(ptr)` can return `EFAULT` when `GC.compact` is running because `ptr` can point read-barrier protected pages (embed strings).
Reproducible steps:
Apply the following patch to increase possibility:
```patch
diff --git a/io.c b/io.c
index f6cd2c1a56..83d67ba2dc 100644
--- a/io.c
+++ b/io.c
@@ -1212,8 +1212,12 @@ internal_write_func(void *ptr)
}
}
+ int cnt = 0;
retry:
- do_write_retry(write(iis->fd, iis->buf, iis->capa));
+ for (; cnt < 1000; cnt++) {
+ do_write_retry(write(iis->fd, iis->buf, iis->capa));
+ if (result <= 0) break;
+ }
if (result < 0 && !iis->nonblock) {
int e = errno;
```
Run the following code:
```ruby
t1 = Thread.new{ 10_000.times.map{"#{_1}"}; GC.compact while true }
t2 = Thread.new{
i=0
$stdout.write "<#{i+=1}>" while true
}
t2.join
```
and
```
$ make run
(snip)
4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4>#<Thread:0x00007fa61b4dd758 ../../src/trunk/test.rb:3 run> terminated with exception (report_on_exception is true):
../../src/trunk/test.rb:5:in `write': Bad address @ io_write - <STDOUT> (Errno::EFAULT)
from ../../src/trunk/test.rb:5:in `block in <main>'
../../src/trunk/test.rb:5:in `write': Bad address @ io_write - <STDOUT> (Errno::EFAULT)
from ../../src/trunk/test.rb:5:in `block in <main>'
make: *** [uncommon.mk:1383: run] Error 1
```
I think this is why we get `EFAULT` on CI. To increase possibilities running many busy processes (`ruby -e 'loop{}'` for example) will help (and on CI environment there are such busy processes accidentally).
--
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- ruby-core@ml.ruby-lang.org
To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/
next prev parent reply other threads:[~2024-01-16 9:34 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-01-09 10:37 [ruby-core:116114] [Ruby master Bug#20169] `GC.compact` can raises `EFAULT` on IO ko1 (Koichi Sasada) via ruby-core
2024-01-09 11:05 ` [ruby-core:116115] " kjtsanaktsidis (KJ Tsanaktsidis) via ruby-core
2024-01-10 23:39 ` [ruby-core:116164] " kjtsanaktsidis (KJ Tsanaktsidis) via ruby-core
2024-01-11 3:28 ` [ruby-core:116167] " luke-gru (Luke Gruber) via ruby-core
2024-01-13 2:58 ` [ruby-core:116188] " kjtsanaktsidis (KJ Tsanaktsidis) via ruby-core
2024-01-15 5:25 ` [ruby-core:116212] " kjtsanaktsidis (KJ Tsanaktsidis) via ruby-core
2024-01-16 9:34 ` kjtsanaktsidis (KJ Tsanaktsidis) via ruby-core [this message]
2024-02-02 17:03 ` [ruby-core:116560] " peterzhu2118 (Peter Zhu) via ruby-core
2024-02-03 1:37 ` [ruby-core:116562] " kjtsanaktsidis (KJ Tsanaktsidis) via ruby-core
2024-02-04 22:14 ` [ruby-core:116577] " peterzhu2118 (Peter Zhu) via ruby-core
2024-02-04 23:41 ` [ruby-core:116578] " kjtsanaktsidis (KJ Tsanaktsidis) via ruby-core
2024-05-28 21:24 ` [ruby-core:118049] " k0kubun (Takashi Kokubun) via ruby-core
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.ruby-lang.org/en/community/mailing-lists/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=redmine.journal-106244.20240116093441.17@ruby-lang.org \
--to=ruby-core@ruby-lang.org \
--cc=noreply@ruby-lang.org \
--cc=ruby-core@ml.ruby-lang.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).