Skip to content

Commit

Permalink
Pin frozen messages to their arena to prevent garbage collection. (#1…
Browse files Browse the repository at this point in the history
…3420)

Fixes a class of flaky test failures observed only in the FFI implementation due to garbage collection in between calls to an accessors for a frozen field.

Closes #13420

COPYBARA_INTEGRATE_REVIEW=#13420 from protocolbuffers:rub 0ea9116
PiperOrigin-RevId: 552602026
  • Loading branch information
JasonLunn authored and copybara-github committed Jul 31, 2023
1 parent 43e1657 commit 1ce24c5
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 0 deletions.
6 changes: 6 additions & 0 deletions ruby/lib/google/protobuf/ffi/internal/arena.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ module Google
module Protobuf
module Internal
class Arena
attr :pinned_messages

# FFI Interface methods and setup
extend ::FFI::DataConverter
Expand All @@ -59,6 +60,7 @@ def from_native(value, _)

def initialize(pointer)
@arena = ::FFI::AutoPointer.new(pointer, Google::Protobuf::FFI.method(:free_arena))
@pinned_messages = []
end

def fuse(other_arena)
Expand All @@ -67,6 +69,10 @@ def fuse(other_arena)
raise RuntimeError.new "Unable to fuse arenas. This should never happen since Ruby does not use initial blocks"
end
end

def pin(message)
pinned_messages.push message
end
end
end

Expand Down
6 changes: 6 additions & 0 deletions ruby/lib/google/protobuf/ffi/message.rb
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@ def self.new(initial_value = nil)
instance
end

def freeze
super
@arena.pin self
self
end

def dup
duplicate = self.class.private_constructor(@arena)
mini_table = Google::Protobuf::FFI.get_mini_table(self.class.descriptor)
Expand Down

0 comments on commit 1ce24c5

Please sign in to comment.