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

rb_str_locktmp: raises when called on a Frozen String #3752

Open
byroot opened this issue Dec 27, 2024 · 3 comments
Open

rb_str_locktmp: raises when called on a Frozen String #3752

byroot opened this issue Dec 27, 2024 · 3 comments

Comments

@byroot
Copy link

byroot commented Dec 27, 2024

Ref: ruby/openssl#831

RuntimeError: temporal locking immutable string
string.c:102:in `rb_str_locktmp'
string.c:102:in `rb_str_locktmp'
/home/runner/.rubies/truffleruby-24.1.1/lib/truffle/truffle/cext_ruby.rb:38:in `syswrite_nonblock'

Whereas MRI doesn't care whether the string is frozen or not, it will lock it either way:

VALUE
rb_str_locktmp(VALUE str)
{
    if (FL_TEST(str, STR_TMPLOCK)) {
        rb_raise(rb_eRuntimeError, "temporal locking already locked string");
    }
    FL_SET(str, STR_TMPLOCK);
    return str;
}

VALUE
rb_str_unlocktmp(VALUE str)
{
    if (!FL_TEST(str, STR_TMPLOCK)) {
        rb_raise(rb_eRuntimeError, "temporal unlocking already unlocked string");
    }
    FL_UNSET(str, STR_TMPLOCK);
    return str;
}

cc @eregon @nirvdrum

@eregon
Copy link
Member

eregon commented Dec 29, 2024

It's from

@Specialization
RubyString rbStrLockTmpImmutable(ImmutableRubyString string) {
throw new RaiseException(getContext(),
coreExceptions().runtimeError("temporal locking immutable string", this));
}

From a very quick look the error is because rb_str_locktmp() is called on a truly-immutable string (e.g. a frozen string literal or String#-@ or Symbol#name).
That means it shouldn't have state, which also means it shouldn't be possible to lock it.

Isn't string locking meant to avoid concurrent modifications to a string and so shouldn't be done if the string is frozen or indicates a bug in the caller (trying to mutate a frozen string)?

rb_str_locktmp() could be noop for immutable strings, but is that correct? If something queries whether it's locked then it wouldn't reflect it.

@byroot
Copy link
Author

byroot commented Dec 29, 2024

rb_str_locktmp() could be noop for immutable strings, but is that correct? If something queries whether it's locked then it wouldn't reflect it.

Yeah, not too sure. We probably should add some specs after that. IMO it would be OK for locktmp to noop on frozen strings, as long as it's speced. But yes, that could be surprising to some people.

@eregon
Copy link
Member

eregon commented Dec 29, 2024

Probably we should ask on https://bugs.ruby-lang.org/.
In my understanding, and given https://github.com/ruby/ruby/blob/3650f2460f9f58ed188ad289cfb46a1d005d2538/include/ruby/internal/intern/string.h#L615 and https://github.com/ruby/ruby/blob/3650f2460f9f58ed188ad289cfb46a1d005d2538/spec/ruby/optional/capi/string_spec.rb#L1205-L1209 I think CRuby should assert !frozen in rb_str_locktmp() & rb_str_unlocktmp().

I also wonder if as a side effect of rb_str_locktmp(frozen_string), trying to mutate that frozen string raises another error and not the correct FrozenError.

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

No branches or pull requests

3 participants