From: nagachika00@gmail.com
To: ruby-core@ruby-lang.org
Subject: [ruby-core:90998] [Ruby trunk Bug#15362] [PATCH] Avoid GCing dead stack after switching away from a fiber
Date: Thu, 10 Jan 2019 14:18:50 +0000 (UTC) [thread overview]
Message-ID: <redmine.journal-76218.20190110141848.188cd88620f3fdb5@ruby-lang.org> (raw)
In-Reply-To: redmine.issue-15362.20181130202250@ruby-lang.org
Issue #15362 has been updated by nagachika (Tomoyuki Chikanaga).
Backport changed from 2.5: REQUIRED to 2.5: DONE
ruby_2_5 r66777 merged revision(s) 66111.
----------------------------------------
Bug #15362: [PATCH] Avoid GCing dead stack after switching away from a fiber
https://bugs.ruby-lang.org/issues/15362#change-76218
* Author: alanwu (Alan Wu)
* Status: Closed
* Priority: Normal
* Assignee: ioquatix (Samuel Williams)
* Target version: 2.6
* ruby -v:
* Backport: 2.5: DONE
----------------------------------------
Hello! I have a patch that fixes Bug #14561. It's not a platform specific issue but
it affects the default build configuration for MacOS and is causing segfaults on 2.5.x.
I've put the test for this in a separate patch because I'm not sure if we want to have
a 5 second test that only matters for non-default build configs and doesn't catch things reliably on Linux.
I tested this on both trunk and ruby_2_5, on MacOS and on Linux, on various build configs.
Please let me know if anything in my understanding is wrong. I've pasted my commit message below.
----
Fibers save execution contextes, and execution contexts include a native
stack pointer. It may happen that a Fiber outlive the native thread
it executed on. Consider the following code adapted from Bug #14561:
```ruby
enum = Enumerator.new { |y| y << 1 }
thread = Thread.new { enum.peek } # fiber constructed inside the
# block and saved inside `enum`
thread.join
sleep 5 # thread finishes and thread cache wait time runs out.
# Native thread exits, possibly freeing its stack.
GC.start # segfault because GC tires to mark the dangling stack pointer
# inside `enum`'s fiber
```
The problem is masked by FIBER_USE_COROUTINE and FIBER_USE_NATIVE,
as those implementations already do what this commit does.
Generally on Linux systems, FIBER_USE_NATIVE is 1 even when
one uses `./configure --disable-fiber-coroutine`, since most
Linux systems have getcontext() and setcontext() which
turns on FIBER_USE_NATIVE. (compile with `make
DEFS="-DFIBER_USE_NATIVE=0" to explicitly disable it)
Furthermore, when both FIBER_USE_COROUTINE and FIBER_USE_NATIVE
are off, and the GC reads from the stack of a dead native
thread, MRI does not segfault on Linux. This is probably due to
libpthread not marking the page where the dead stack lives as
unreadable. Nevertheless, this use-after-free is visible through
Valgrind.
On ruby_2_5, this is an acute problem, since it doesn't have FIBER_USE_COROUTINE.
Thread cache is also unavailable for 2.5.x, triggering this issue
more often. (thread cache gives this bug a grace period since
it makes native threads wait a little before exiting)
This issue is very visible on MacOS on 2.5.x since libpthread marks
the dead stack as unreadable, consistently turning this use-after-free
into a segfault.
Fixes Bug #14561
* cont.c: Set saved_ec.machine.stack_end to NULL when switching away from a
fiber to keep the GC marking it. `saved_ec` gets rehydrated with a
stack pointer if/when the fiber runs again.
---Files--------------------------------
0001-Avoid-GCing-dead-stack-after-switching-away-from-a-f.patch (2.63 KB)
0001-Add-a-test-for-Bug-14561.patch (1.21 KB)
--
https://bugs.ruby-lang.org/
prev parent reply other threads:[~2019-01-10 14:18 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <redmine.issue-15362.20181130202250@ruby-lang.org>
2018-11-30 20:22 ` [ruby-core:90193] [Ruby trunk Bug#15362] [PATCH] Avoid GCing dead stack after switching away from a fiber alanwucanada
2018-11-30 22:47 ` [ruby-core:90196] " aselder
2018-12-01 3:21 ` [ruby-core:90199] " samuel
2018-12-01 3:51 ` [ruby-core:90200] " samuel
2018-12-01 4:57 ` [ruby-core:90201] " samuel
2018-12-01 5:07 ` [ruby-core:90203] " Eric Wong
2018-12-01 5:01 ` [ruby-core:90202] " samuel
2018-12-01 5:26 ` [ruby-core:90204] " samuel
2018-12-01 6:05 ` [ruby-core:90205] " samuel
2018-12-01 6:42 ` [ruby-core:90206] " Eric Wong
2018-12-01 6:50 ` [ruby-core:90207] [Ruby trunk Bug#15362][Closed] " samuel
2018-12-01 17:16 ` [ruby-core:90216] [Ruby trunk Bug#15362] " alanwucanada
2018-12-14 21:32 ` [ruby-core:90534] " dazuma
2018-12-31 19:30 ` [ruby-core:90840] " aselder
2019-01-10 14:18 ` nagachika00 [this message]
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-76218.20190110141848.188cd88620f3fdb5@ruby-lang.org \
--to=ruby-core@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).