Skip to content

Commit

Permalink
Fix for race in lazy initialization of handlers.
Browse files Browse the repository at this point in the history
  • Loading branch information
haberman committed Aug 20, 2019
1 parent ee4f249 commit b245551
Showing 1 changed file with 21 additions and 0 deletions.
21 changes: 21 additions & 0 deletions ruby/ext/google/protobuf_c/defs.c
Expand Up @@ -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 };
def = rb_class_new_instance(3, args, klass);
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_done(&it);
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;
Expand Down

0 comments on commit b245551

Please sign in to comment.