Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move parse frame array to the Map object #3560

Merged
merged 2 commits into from Aug 31, 2017

Conversation

tenderlove
Copy link
Contributor

This makes the frame stack per-parser, and per-thread. Fixes #3250

@grpc-kokoro
Copy link

Thanks for your pull request. The automated tests will run as soon as one of the admins verifies this change is ok for us to run on our infrastructure.

1 similar comment
@grpc-kokoro
Copy link

Thanks for your pull request. The automated tests will run as soon as one of the admins verifies this change is ok for us to run on our infrastructure.

@bazel-io
Copy link

Can one of the admins verify this patch?

@googlebot
Copy link

Thanks for your pull request. It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

📝 Please visit https://cla.developers.google.com/ to sign.

Once you've signed, please reply here (e.g. I signed it!) and we'll verify. Thanks.


  • If you've already signed a CLA, it's possible we don't have your GitHub username or you're using a different email address. Check your existing CLA data and verify that your email is set on your git commits.
  • If your company signed a CLA, they designated a Point of Contact who decides which employees are authorized to participate. You may need to contact the Point of Contact for your company and ask to be added to the group of authorized contributors. If you don't know who your Point of Contact is, direct the project maintainer to go/cla#troubleshoot.
  • In order to pass this check, please resolve this problem and have the pull request author add another comment and the bot will run again.

@tenderlove
Copy link
Contributor Author

Once you've signed, please reply here (e.g. I signed it!) and we'll verify. Thanks.

I signed it!

@googlebot
Copy link

CLAs look good, thanks!

@grpc-kokoro
Copy link

Thanks for your pull request. The automated tests will run as soon as one of the admins verifies this change is ok for us to run on our infrastructure.

1 similar comment
@grpc-kokoro
Copy link

Thanks for your pull request. The automated tests will run as soon as one of the admins verifies this change is ok for us to run on our infrastructure.

@bazel-io
Copy link

Can one of the admins verify this patch?

@liujisi
Copy link
Contributor

liujisi commented Aug 24, 2017

ok to test

@tenderlove
Copy link
Contributor Author

I see that some builds failed, but I can't see the details. Do I need to make sure that all of them are green before this can be applied?

@liujisi
Copy link
Contributor

liujisi commented Aug 28, 2017

I believe it's just flaky. The tests result look good. @haberman could you take a look at the PR?

@haberman
Copy link
Member

Thanks very much for the fix! Can you help me understand what could cause concurrent decodes though? I know Ruby can have multiple threads, but I was under the impression that Ruby has a GVL that prevents Ruby code or C extensions from running concurrently (unless you use rb_thread_call_without_gvl): https://github.com/ruby/ruby/blob/trunk/doc/extension.rdoc#threading

@tenderlove
Copy link
Contributor Author

Thanks very much for the fix! Can you help me understand what could cause concurrent decodes though?

Ruby can switch threads when the GC is invoked. Array manipulations with rb_ary_push / rb_ary_pop may cause the GC to be invoked and allow threads to switch. If the array was implemented with a non-Ruby data structure, then the VM would not be given an opportunity to switch threads.

I know Ruby can have multiple threads, but I was under the impression that Ruby has a GVL that prevents Ruby code or C extensions from running concurrently

It sounds like you might be confusing concurrency and parallelism. The GVL prevents parallelism (two Ruby threads running at the same time), but it does not prevent concurrency (two Ruby threads running interleaved).

The bug that we are hitting here is that we have two decodes running interleaved. Interleaving thread execution happened because the calls to rb_ary_* allowed a different thread to be scheduled. These interleaved executions both mutated a shared array, and that leads to a SEGV or "strange values for a key in the ruby object".

I hope this helps. If there's anything I can do to better explain, please let me know!

NOTE: It may not have been the rb_ary_* functions that allowed the thread to switch, they are just the ones that stuck out to me. Many rb_* calls allow threads to switch (especially if they hit the GC or do IO operations).

@@ -293,16 +288,12 @@ static map_parse_frame_t* map_push_frame(VALUE map,
native_slot_init(handlerdata->key_field_type, &frame->key_storage);
native_slot_init(handlerdata->value_field_type, &frame->value_storage);

rb_ary_push(map_parse_frames,
Map_push_frame(map,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you are storing this in the map directly, I don't think it needs to be an array with push and pop. I think it could just be a single value. The array was for when we had a single global stack that needed to be able to handle parsing of nested maps.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I changed this to store only one value.

@haberman
Copy link
Member

Got it, thanks for the explanation. I hadn't realized that calls into Ruby APIs could release the GVL; I thought every call into a C extension routine was atomic unless you explicitly released the GVL.

Copy link
Member

@haberman haberman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implementation looks great. Could you add your test case to our test suite to verify the fix and prevent regressions?

@tenderlove
Copy link
Contributor Author

Implementation looks great. Could you add your test case to our test suite to verify the fix and prevent regressions?

Done. 😊

Copy link
Member

@haberman haberman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the fix!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants