Skip to content

Fix cext support for google-protobuf #3861

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

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

nirvdrum
Copy link
Collaborator

While trying to run the google-protobuf test suite I ran into a couple of problems related to native extensions.

  1. The way we implement RB_OBJ_FROZEN could lead to infinite recursion. At least one of the Protobuf types defines frozen? and use RB_OBJ_FROZEN to avoid a loop. I resolved that issue by adding a new primitive.
  2. The google-protobuf extension needs rb_error_frozen_object.

I didn't add a spec for rb_error_frozen_object, partially because it wasn't clear where to put it. The function only seems to be called in MRI when instance_variable_set is invoked on a special const. Also, I added the function to error.c because that's where it lives in MRI. But, I see we have other functions that we've moved from error.c to exception.c (or, they moved in MRI and we didn't update to match). I don't particularly care where we put it; I can move it if anyone has a strong preference.

There may be other compatibility issues to resolve in order to get the gem fully functional. But, it's hard for me to tell due to the crash in #3860.

nirvdrum added 3 commits May 10, 2025 21:52
…`frozen?`.

MRI defines `frozen?` with `rb_obj_frozen_p`, which in turn, uses `RB_OBJ_FROZEN`. Since TruffleRuby doesn't have flag bits in an object header like MRI does, we implement `RB_OBJ_FROZEN` with `rb_obj_frozen_p`, which would lead to an infinite loop if a native extension redefined `frozen?` in terms of `RB_OBJ_FROZEN`. We break the loop by introducing a new primitive, which a native extension would not be able to redefine.
@oracle-contributor-agreement oracle-contributor-agreement bot added the OCA Verified All contributors have signed the Oracle Contributor Agreement. label May 11, 2025
@nirvdrum nirvdrum added shopify Pull requests from Shopify cexts compatibility and removed OCA Verified All contributors have signed the Oracle Contributor Agreement. labels May 11, 2025
Copy link
Member

@eregon eregon left a comment

Choose a reason for hiding this comment

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

Thank you for the fixes!

@@ -49,3 +49,8 @@ bool rb_warning_category_enabled_p(rb_warning_category_t category) {
void rb_tr_warn_va_list(const char *fmt, va_list args) {
RUBY_CEXT_INVOKE("rb_tr_warn", rb_vsprintf(fmt, args));
}

void rb_error_frozen_object(VALUE frozen_obj) {
Copy link
Member

Choose a reason for hiding this comment

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

Could you move it to exception.c?
In general we don't follow whatever the .c file is in CRuby, instead we group by function prefix as documented by a comment at the top of the file.

BTW I'm not sure why we even have this file named as error.c, it should be renamed to warning.c. Could be done in this PR too while we noticed it.

@@ -2347,6 +2347,10 @@ def rb_eval_cmd_kw(cmd, args, kw_splat)
end
end

def rb_error_frozen_object(object)
Copy link
Member

Choose a reason for hiding this comment

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

Could you add a C API spec in exception_spec.c/rb? (to ensure it works as expected and it's not untested code)

@@ -410,6 +410,16 @@ static VALUE object_spec_custom_alloc_func_p(VALUE self, VALUE klass) {
return allocator ? Qtrue : Qfalse;
}

static VALUE object_spec_redefine_rb_obj_frozen_p(VALUE self) {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
static VALUE object_spec_redefine_rb_obj_frozen_p(VALUE self) {
static VALUE object_spec_redefine_frozen(VALUE self) {

redefine_rb_obj_frozen_p sounds too confusing to me, we can't redefine a C function

@@ -410,6 +410,16 @@ static VALUE object_spec_custom_alloc_func_p(VALUE self, VALUE klass) {
return allocator ? Qtrue : Qfalse;
}

static VALUE object_spec_redefine_rb_obj_frozen_p(VALUE self) {
// The purpose of this spec is to verify that `rb_obj_frozen_p`
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// The purpose of this spec is to verify that `rb_obj_frozen_p`
// The purpose of this spec is to verify that `obj.frozen?`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cexts compatibility shopify Pull requests from Shopify
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants