Skip to content

Commit

Permalink
fix: possible race condition extending native class
Browse files Browse the repository at this point in the history
  • Loading branch information
edusperoni committed Sep 16, 2024
1 parent e6f0c5e commit 8b932a3
Showing 1 changed file with 25 additions and 18 deletions.
43 changes: 25 additions & 18 deletions NativeScript/runtime/ClassBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,34 @@

namespace tns {

// Moved this method in a separate .cpp file because ARC destroys the class created with objc_allocateClassPair
// when the control leaves this method scope
// Moved this method in a separate .cpp file because ARC destroys the class
// created with objc_allocateClassPair when the control leaves this method scope

Class ClassBuilder::GetExtendedClass(std::string baseClassName, std::string staticClassName) {
Class baseClass = objc_getClass(baseClassName.c_str());
std::string name = !staticClassName.empty() ? staticClassName : baseClassName + "_" + std::to_string(++ClassBuilder::classNameCounter_);
Class clazz = objc_getClass(name.c_str());
Class ClassBuilder::GetExtendedClass(std::string baseClassName,
std::string staticClassName) {
Class baseClass = objc_getClass(baseClassName.c_str());
std::string name =
!staticClassName.empty()
? staticClassName
: baseClassName + "_" +
std::to_string(++ClassBuilder::classNameCounter_);
// here we could either call objc_getClass with the name to see if the class
// already exists or we can just try allocating it, which will return nil if
// the class already exists so we try allocating it every time to avoid race
// conditions in case this method is being executed by multiple threads
Class clazz = objc_allocateClassPair(baseClass, name.c_str(), 0);

if (clazz != nil) {
int i = 1;
std::string initialName = name;
while (clazz != nil) {
name = initialName + std::to_string(i++);
clazz = objc_getClass(name.c_str());
}
if (clazz == nil) {
int i = 1;
std::string initialName = name;
while (clazz == nil) {
name = initialName + std::to_string(i++);
clazz = objc_allocateClassPair(baseClass, name.c_str(), 0);
}
}

clazz = objc_allocateClassPair(baseClass, name.c_str(), 0);

objc_registerClassPair(clazz);
return clazz;
objc_registerClassPair(clazz);
return clazz;
}

}
} // namespace tns

0 comments on commit 8b932a3

Please sign in to comment.