Skip to content
Browse files

Merge pull request #6541 from haberman/ruby_race_fix

Fix for race in lazy initialization of handlers.
  • Loading branch information...
haberman committed Aug 20, 2019
2 parents 35b0a87 + b245551 commit 63e4a3ecc956cbab6714b25e8b868765ea7e6fe5
Showing with 21 additions and 0 deletions.
  1. +21 −0 ruby/ext/google/protobuf_c/defs.c
@@ -2228,6 +2228,27 @@ static VALUE get_def_obj(VALUE _descriptor_pool, const void* ptr, VALUE klass) {
VALUE args[3] = { c_only_cookie, _descriptor_pool, key }; VALUE args[3] = { c_only_cookie, _descriptor_pool, key };
def = rb_class_new_instance(3, args, klass); def = rb_class_new_instance(3, args, klass);
rb_hash_aset(descriptor_pool->def_to_descriptor, key, def); rb_hash_aset(descriptor_pool->def_to_descriptor, key, def);

// For message defs, we now eagerly get/create descriptors for all
// submessages. We will need these anyway to parse or serialize this
// message type. But more importantly, we must do this now so that
// add_handlers_for_message() (which calls get_msgdef_obj()) does *not*
// need to create a Ruby object or insert into a Ruby Hash. We need to
// avoid triggering GC, which can switch Ruby threads and re-enter our
// C extension from a different thread. This wreaks havoc on our state
// if we were in the middle of building handlers.
if (klass == cDescriptor) {
const upb_msgdef *m = ptr;
upb_msg_field_iter it;
for (upb_msg_field_begin(&it, m);
upb_msg_field_next(&it)) {
const upb_fielddef* f = upb_msg_iter_field(&it);
if (upb_fielddef_issubmsg(f)) {
get_msgdef_obj(_descriptor_pool, upb_fielddef_msgsubdef(f));
} }

return def; return def;

0 comments on commit 63e4a3e

Please sign in to comment.
You can’t perform that action at this time.