Skip to content

Commit

Permalink
fixup! Fix: GC safety of Thread#start
Browse files Browse the repository at this point in the history
  • Loading branch information
ysbaddaden committed May 6, 2024
1 parent 7195a8b commit b52c19f
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 9 deletions.
14 changes: 8 additions & 6 deletions src/crystal/system/thread.cr
Original file line number Diff line number Diff line change
Expand Up @@ -140,14 +140,16 @@ class Thread
rescue ex
@exception = ex
ensure
# to shutdown the thread we first call any function that needs to access
# local or instance variables, then start cleaning up references (that
# may be the last reference, so the GC may collect them anytime):
detach { system_close }
Fiber.inactive(fiber)
{% if flag?(:preview_mt) %}
# fix the thread stack now so we can start cleaning up references
GC.lock_read
GC.set_stackbottom(thread, fiber.@stack_bottom)
GC.unlock_read
{% end %}

# eventually forget the thread reference (must be the last thing to do)
Thread.threads.delete(self)
Fiber.inactive(fiber)
detach { system_close }
end
end

Expand Down
11 changes: 8 additions & 3 deletions src/gc/boehm.cr
Original file line number Diff line number Diff line change
Expand Up @@ -298,10 +298,10 @@ module GC

# :nodoc:
{% if flag?(:preview_mt) %}
def self.set_stackbottom(thread_handle : Void*, stack_bottom : Void*)
def self.set_stackbottom(thread : Thread, stack_bottom : Void*)
sb = LibGC::StackBase.new
sb.mem_base = stack_bottom
LibGC.set_stackbottom(thread_handle, pointerof(sb))
LibGC.set_stackbottom(thread.gc_thread_handler, pointerof(sb))
end
{% elsif LibGC.has_method?(:set_stackbottom) %}
# this is necessary because Boehm GC does _not_ use `GC_stackbottom` on
Expand Down Expand Up @@ -373,9 +373,14 @@ module GC
end

{% if flag?(:preview_mt) %}
# update the thread stacks to their currently running fiber stacks, we
# only do it once _here_ instead of everytime we switch.
#
# A thread may not have a current fiber while starting, in which case we
# assume the GC knows about the thread and detected its stack.
Thread.unsafe_each do |thread|
if fiber = thread.current_fiber?
GC.set_stackbottom(thread.gc_thread_handler, fiber.@stack_bottom)
GC.set_stackbottom(thread, fiber.@stack_bottom)
end
end
{% end %}
Expand Down

0 comments on commit b52c19f

Please sign in to comment.