Skip to content

Commit 6e4a8cb

Browse files
committed
fix: possible race condition extending native class
1 parent e6f0c5e commit 6e4a8cb

File tree

1 file changed

+25
-18
lines changed

1 file changed

+25
-18
lines changed

NativeScript/runtime/ClassBuilder.cpp

+25-18
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,34 @@
22

33
namespace tns {
44

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

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

13-
if (clazz != nil) {
14-
int i = 1;
15-
std::string initialName = name;
16-
while (clazz != nil) {
17-
name = initialName + std::to_string(i++);
18-
clazz = objc_getClass(name.c_str());
19-
}
22+
if (clazz != nil) {
23+
int i = 1;
24+
std::string initialName = name;
25+
while (clazz != nil) {
26+
name = initialName + std::to_string(i++);
27+
clazz = objc_allocateClassPair(baseClass, name.c_str(), 0);
2028
}
29+
}
2130

22-
clazz = objc_allocateClassPair(baseClass, name.c_str(), 0);
23-
24-
objc_registerClassPair(clazz);
25-
return clazz;
31+
objc_registerClassPair(clazz);
32+
return clazz;
2633
}
2734

28-
}
35+
} // namespace tns

0 commit comments

Comments
 (0)