ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
From: samuel@oriontransfer.net
To: ruby-core@ruby-lang.org
Subject: [ruby-core:90207] [Ruby trunk Bug#15362][Closed] [PATCH] Avoid GCing dead stack after switching away from a fiber
Date: Sat, 01 Dec 2018 06:50:59 +0000 (UTC)	[thread overview]
Message-ID: <redmine.journal-75329.20181201065058.de467f91fba4bddb@ruby-lang.org> (raw)
In-Reply-To: redmine.issue-15362.20181130202250@ruby-lang.org

Issue #15362 has been updated by ioquatix (Samuel Williams).

Status changed from Open to Closed

Okay, I think we are in agreement then.

----------------------------------------
Bug #15362: [PATCH] Avoid GCing dead stack after switching away from a fiber
https://bugs.ruby-lang.org/issues/15362#change-75329

* Author: alanwu (Alan Wu)
* Status: Closed
* Priority: Normal
* Assignee: ioquatix (Samuel Williams)
* Target version: 2.6
* ruby -v: 
* Backport: 2.5: REQUIRED
----------------------------------------
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/

  parent reply	other threads:[~2018-12-01  6:51 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 ` samuel [this message]
2018-12-01 17:16 ` [ruby-core:90216] " alanwucanada
2018-12-14 21:32 ` [ruby-core:90534] " dazuma
2018-12-31 19:30 ` [ruby-core:90840] " aselder
2019-01-10 14:18 ` [ruby-core:90998] " nagachika00

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-75329.20181201065058.de467f91fba4bddb@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).