-
Notifications
You must be signed in to change notification settings - Fork 39
The way rock constructs class information can lead to data races in seemingly unrelated code #1003
Open
Description
Here is a sample _class() function the backend generates lifted from the following class:
Foo: class { init: func bar: func }
test__FooClass *test__Foo_class(){ static _Bool __done__ = false; static test__FooClass class = { { { { .instanceSize = sizeof(test__Foo), .size = sizeof(void*) }, .__defaults__ = (void*) test__Foo___defaults___impl, .__destroy__ = (void*) lang_types__Object___destroy___impl, }, }, .bar = (void*) test__Foo_bar_impl, }; lang_types__Class *classPtr = (lang_types__Class *) &class; if(!__done__){ classPtr->super = (lang_types__Class*) lang_types__Object_class(); __done__ = true; classPtr->name = (void*) lang_String__makeStringLiteral("Foo", 3); } return &class; }
Obviously, this function is not thread safe.
Proposed generated code:
const test__FooClass test__Foo_class = { { { { .instanceSize = sizeof(test__Foo), .size = sizeof(void*), .name = lang_String__makeStringLiteral("Foo", 3) }, .__defaults__ = (void*) test__Foo___defaults___impl, .__destroy__ = (void*) lang_types__Object___destroy___impl, }, }, .bar = (void*) test__Foo_bar_impl, };
Also, anywhere test__Foo_class() would appear, we replace it with &test__Foo_class.