Skip to content

[Ruby] Composed CallCredentials keep a reference to their source#41782

Closed
etiennebarrie wants to merge 2 commits into
grpc:masterfrom
Shopify:ruby-composed-callcredentials-keep-a-reference-to-their-source
Closed

[Ruby] Composed CallCredentials keep a reference to their source#41782
etiennebarrie wants to merge 2 commits into
grpc:masterfrom
Shopify:ruby-composed-callcredentials-keep-a-reference-to-their-source

Conversation

@etiennebarrie

Copy link
Copy Markdown
Contributor

Fix #41781

Looking at the backtrace, we can see it happens when the Proc generating credentials metadata gets called here:

VALUE metadata =
rb_funcall(callback_func, rb_intern("call"), 1, callback_args);

The proc is stored here to be marked by the Ruby GC on the CallCredentials object itself:

wrapper->mark = proc;

It's possible to compose CallCredentials. The CallCredentials#compose method does keep marking the arguments passed to it by collecting them:

mark = rb_ary_new();
creds = grpc_rb_get_wrapped_call_credentials(self);
for (int i = 0; i < argc; i++) {
rb_ary_push(mark, argv[i]);

and passing them in the wrapping struct to be stored and later marked:
return grpc_rb_wrap_call_credentials(creds, mark);

However it does not keep self to mark, which means that if you have two call credentials, combine them, keep the result but get rid of the two original objects, only the second one and its Proc will be marked, but the Proc of the first one can be garbage collected and then cause the crash we're seeing.

The test reproduces the issue, crashes on main, but passes with the fix.

When building composed CallCredentials, we not only need to keep a
reference to all the CallCredentials passed as arguments, but also
`self`.
@linux-foundation-easycla

linux-foundation-easycla Bot commented Mar 3, 2026

Copy link
Copy Markdown

CLA Signed
The committers listed above are authorized under a signed CLA.

@asheshvidyut

Copy link
Copy Markdown
Member

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request correctly addresses a garbage collection issue with composed CallCredentials by ensuring the self object is also marked to be kept alive. The added regression test effectively reproduces the problem and verifies the fix. The changes look good.

@asheshvidyut asheshvidyut left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for the PR @etiennebarrie

LGTM 🚀

I have tested and verified this PR running the following commands.

cd grpc 
bundle exec rake compile
cd grpc/src/ruby
bundle exec rspec spec/client_server_spec.rb

@asheshvidyut asheshvidyut added release notes: no Indicates if PR should not be in release notes release notes: yes Indicates if PR needs to be in release notes and removed release notes: no Indicates if PR should not be in release notes labels Mar 8, 2026

@zarinn3pal zarinn3pal left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

Zgoda91 pushed a commit to Zgoda91/grpc that referenced this pull request Mar 22, 2026
…c#41782)

Fix grpc#41781

Looking at the backtrace, we can see it happens when the Proc generating credentials metadata gets called here: https://github.com/grpc/grpc/blob/093085cc925e0d5aa6e92bc29e917f9bdc00add2/src/ruby/ext/grpc/rb_call_credentials.c#L88-L89

The proc is stored here to be marked by the Ruby GC on the CallCredentials object itself:
https://github.com/grpc/grpc/blob/093085cc925e0d5aa6e92bc29e917f9bdc00add2/src/ruby/ext/grpc/rb_call_credentials.c#L292

It's possible to compose CallCredentials. The `CallCredentials#compose` method does keep marking the arguments passed to it by collecting them:
https://github.com/grpc/grpc/blob/093085cc925e0d5aa6e92bc29e917f9bdc00add2/src/ruby/ext/grpc/rb_call_credentials.c#L308-L311
and passing them in the wrapping struct to be stored and later marked:
https://github.com/grpc/grpc/blob/093085cc925e0d5aa6e92bc29e917f9bdc00add2/src/ruby/ext/grpc/rb_call_credentials.c#L319

However it does not keep `self` to mark, which means that if you have two call credentials, combine them, keep the result but get rid of the two original objects, only the second one and its Proc will be marked, but the Proc of the first one can be garbage collected and then cause the crash we're seeing.

The test reproduces the issue, crashes on main, but passes with the fix.

Closes grpc#41782

COPYBARA_INTEGRATE_REVIEW=grpc#41782 from Shopify:ruby-composed-callcredentials-keep-a-reference-to-their-source 4850fc1
PiperOrigin-RevId: 882286618
asheshvidyut pushed a commit to asheshvidyut/grpc that referenced this pull request Mar 26, 2026
…c#41782)

Fix grpc#41781

Looking at the backtrace, we can see it happens when the Proc generating credentials metadata gets called here: https://github.com/grpc/grpc/blob/093085cc925e0d5aa6e92bc29e917f9bdc00add2/src/ruby/ext/grpc/rb_call_credentials.c#L88-L89

The proc is stored here to be marked by the Ruby GC on the CallCredentials object itself:
https://github.com/grpc/grpc/blob/093085cc925e0d5aa6e92bc29e917f9bdc00add2/src/ruby/ext/grpc/rb_call_credentials.c#L292

It's possible to compose CallCredentials. The `CallCredentials#compose` method does keep marking the arguments passed to it by collecting them:
https://github.com/grpc/grpc/blob/093085cc925e0d5aa6e92bc29e917f9bdc00add2/src/ruby/ext/grpc/rb_call_credentials.c#L308-L311
and passing them in the wrapping struct to be stored and later marked:
https://github.com/grpc/grpc/blob/093085cc925e0d5aa6e92bc29e917f9bdc00add2/src/ruby/ext/grpc/rb_call_credentials.c#L319

However it does not keep `self` to mark, which means that if you have two call credentials, combine them, keep the result but get rid of the two original objects, only the second one and its Proc will be marked, but the Proc of the first one can be garbage collected and then cause the crash we're seeing.

The test reproduces the issue, crashes on main, but passes with the fix.

Closes grpc#41782

COPYBARA_INTEGRATE_REVIEW=grpc#41782 from Shopify:ruby-composed-callcredentials-keep-a-reference-to-their-source 4850fc1
PiperOrigin-RevId: 882286618
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lang/ruby release notes: yes Indicates if PR needs to be in release notes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Ruby] Segfault using credentials

4 participants