Skip to content

Commit

Permalink
Exception::CallStack: avoid allocations in LibC.dl_iterate_phdr (#…
Browse files Browse the repository at this point in the history
…12625)

Calling `self.read_dwarf_sections` directly from the C callback may lead to reallocations and deadlocks due to the internal lock held by `dl_iterate_phdr` (#10084). Work around this by storing object base address and passing it to `self.read_dwarf_sections` later when `dl_iterate_phdr` returns.
  • Loading branch information
dmgk authored Nov 12, 2022
1 parent 1da0e33 commit 6edc9e3
Showing 1 changed file with 9 additions and 6 deletions.
15 changes: 9 additions & 6 deletions src/exception/call_stack/elf.cr
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,19 @@ require "crystal/elf"

struct Exception::CallStack
protected def self.load_debug_info_impl
base_address : LibC::Elf_Addr = 0
phdr_callback = LibC::DlPhdrCallback.new do |info, size, data|
# The first entry is the header for the current program
read_dwarf_sections(info.value.addr)
# The first entry is the header for the current program.
# Note that we avoid allocating here and just store the base address
# to be passed to self.read_dwarf_sections when dl_iterate_phdr returns.
# Calling self.read_dwarf_sections from this callback may lead to reallocations
# and deadlocks due to the internal lock held by dl_iterate_phdr (#10084).
data.as(Pointer(LibC::Elf_Addr)).value = info.value.addr
1
end

# GC needs to be disabled around dl_iterate_phdr in freebsd (#10084)
{% if flag?(:freebsd) %} GC.disable {% end %}
LibC.dl_iterate_phdr(phdr_callback, nil)
{% if flag?(:freebsd) %} GC.enable {% end %}
LibC.dl_iterate_phdr(phdr_callback, pointerof(base_address))
self.read_dwarf_sections(base_address)
end

protected def self.read_dwarf_sections(base_address = 0)
Expand Down

0 comments on commit 6edc9e3

Please sign in to comment.