react-native: Xcode 14.0 beta 4 reports "Hang Risk" in RCTWebSocket
Description
Error reported: Thread running at QOS_CLASS_USER_INTERACTIVE waiting on a lower QoS thread running at QOS_CLASS_DEFAULT. Investigate ways to avoid priority inversions
.
Using Xcode Version 14.0 beta 4 (14A5284g).
Seemingly originates from RCTSRWebSocket.m
Version
0.66.3
Output of npx react-native info
info Fetching system and libraries information… System: OS: macOS 12.5 CPU: (16) x64 Intel® Core™ i9-9880H CPU @ 2.30GHz Memory: 186.13 MB / 16.00 GB Shell: 5.8 - /usr/local/bin/zsh Binaries: Node: 14.17.1 - ~/.nvm/versions/node/v14.17.1/bin/node Yarn: 1.22.10 - ~/src/github.com/umbermoney/daisy/node_modules/.bin/yarn npm: 6.14.13 - ~/.nvm/versions/node/v14.17.1/bin/npm Watchman: 4.9.0 - /usr/local/bin/watchman Managers: CocoaPods: 1.10.1 - /Users/lucas/.rbenv/shims/pod SDKs: iOS SDK: Platforms: DriverKit 21.4, iOS 15.4, macOS 12.3, tvOS 15.4, watchOS 8.5 Android SDK: API Levels: 21, 28, 29, 30 Build Tools: 28.0.3, 29.0.2, 29.0.3, 30.0.2 System Images: android-29 | Google APIs Intel x86 Atom, android-31 | Google APIs Intel x86 Atom_64 Android NDK: Not Found IDEs: Android Studio: 2021.2 AI-212.5712.43.2112.8609683 Xcode: 13.3/13E113 - /usr/bin/xcodebuild Languages: Java: 1.8.0_251 - /Users/lucas/.jenv/shims/javac npmPackages: @react-native-community/cli: Not Found react: 17.0.2 => 17.0.2 react-native: 0.66.3 => 0.66.3 react-native-macos: Not Found npmGlobalPackages: react-native: Not Found
Steps to reproduce
- Create react-native project on Xcode Version 14.0 beta 4 (14A5284g)
- Run application
Snack, code example, screenshot, or link to a repository
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 78
- Comments: 45 (4 by maintainers)
this worked for me as temp measure
described here https://developer.apple.com/documentation/xcode/diagnosing-performance-issues-early
You just turned off the checker, that doesn’t mean the underlying issue is solved.
I had the same problem ( and I finally fixed it without really knowing why…, probably an indexing issue from XCODE 14).
If may be it can help you, these are the steps I follow : 1) I cleaned the build folder from XCODE (Product > Clean Build Folder) 2) I removed the DerivedData folder in ~/Library/Developer/Xcode/DerivedData 3) I restarted my computer
After that, I opened my app workspace from XCODE, a file indexing process started and took a very long time (something like 15 or 20 minutes).
Once indexing process finished, I tried to build again and VOILA, this time it worked !
I really hope it will help you.
Regards,
Jean-Baptiste
My system: OS: macOS 12.6 Monterey CPU: 1.8 GHz Intel Core i5 Memory: 8 GB 1600 Mhz DDR3 Node : v16.17.1 Xcode: 14.0.1 React: 18.1.0 React-native: 0.70.6
I don’t work on React but as I mentioned in my comment above, this issue is pointing to a priority inversion. Priority inversions won’t crash your program but can cause performance issues especially when system is under heavy resource contention. This inversion is coming from the React framework itself. Folks who maintain the React framework should audit their usage of
dispatch_group_wait
– it’s a primitive that doesn’t provide priority inversion avoidance.The link (https://developer.apple.com/documentation/xcode/diagnosing-performance-issues-early) explains how these inversions should be addressed.As for app developers who are seeing this (because they are using React), they should keep an eye on whether this inversion is causing hangs in their app for their app users. If it is, you probably want to deep dive more in the architecture of your app to avoid this inversion.
FWIW, elevating the thread priority suppresses the priority inversion warning:
I have no idea whether this doesn’t negatively affects anything else as I have no clue what it is used for.
That said, it looks like this module has recently been replaced: https://github.com/facebook/react-native/pull/36471
Any updates on this issue, I can reproduce this bug on Fresh react native 0.70.2.
The commit to move SocketRocket to 0.7.0 (which resolves the issue) is already on main: https://github.com/facebook/react-native/commit/bab9c839eaad1ffc358fa5c87440a6de7cbe981b but it doesn’t look like it made it into 0.73.0 or 0.73.1 from what I can see in the release tags.
You could request it to be picked to 0.73.2 here: https://github.com/reactwg/react-native-releases/discussions/95
yes, we are considering it. We couldn’t do it before due to transitive dependencies that would have make other libraries incompatible.
// // Copyright 2012 Square Inc. // Portions Copyright © 2016-present, Facebook, Inc. // // All rights reserved. // // This source code is licensed under the BSD-style license found in the // LICENSE file in the root directory of this source tree. An additional grant // of patent rights can be found in the PATENTS file in the same directory. //
#import “SRRunLoopThread.h” #import <pthread.h> @interface SRRunLoopThread () { dispatch_group_t _waitGroup; }
@property (nonatomic, strong, readwrite) NSRunLoop *runLoop; @property (strong, nonatomic) NSLock *lock1; @property (assign, nonatomic) pthread_mutex_t lock; @property (assign, nonatomic) pthread_cond_t cond; @end
@implementation SRRunLoopThread
(void)dealloc { // 不用需要销毁 pthread_mutex_destroy(&_lock); pthread_cond_destroy(&_cond); }
(void)__initMutex:(pthread_mutex_t *)mutex { // #define PTHREAD_MUTEX_INITIALIZER {_PTHREAD_MUTEX_SIG_init, {0}} // self.mutex = PTHREAD_MUTEX_INITIALIZER;
// 静态初始化方法,所以这里不能用这种方式初始化,用下面👇🏻方法初始化 // 1.初始化属性 pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); /*
// pthread_mutexattr_settype(&attr, NULL); 传空,默认 PTHREAD_MUTEX_DEFAULT pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
// 2.初始化锁 pthread_mutex_init(mutex, &attr);
// 3.销毁属性 pthread_mutexattr_destroy(&attr);
// 初始化条件 pthread_cond_init(&_cond, NULL);
pthread_mutex_lock(mutex); }
(instancetype)init { self = [super init]; if (self) { // _waitGroup = dispatch_group_create(); // dispatch_group_enter(_waitGroup); [self __initMutex:&_lock]; } return self; }
(void)main {
@autoreleasepool { _runLoop = [NSRunLoop currentRunLoop]; // dispatch_group_leave(_waitGroup); // 激活一个等待该条件的线程 pthread_cond_signal(&_cond); NSLog(@“2222”); // Add an empty run loop source to prevent runloop from spinning. CFRunLoopSourceContext sourceCtx = { .version = 0, .info = NULL, .retain = NULL, .release = NULL, .copyDescription = NULL, .equal = NULL, .hash = NULL, .schedule = NULL, .cancel = NULL, .perform = NULL }; CFRunLoopSourceRef source = CFRunLoopSourceCreate(NULL, 0, &sourceCtx); CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode); CFRelease(source);
} }
(NSRunLoop *)runLoop; { // 等待条件(进入休眠,放开mutex锁;被唤醒后,会再次对mutex加锁) pthread_cond_wait(&_cond, &_lock); NSLog(@“1111”); return _runLoop; }
@end
这个是我修改的关于SRRunLoopThread.m 的修复。 通过测试socket 可以正常使用。
+1 This seems present on a Fresh RN upgrade
I’ve seen this alternative PR to fix the issue, https://github.com/facebookincubator/SocketRocket/pull/659, but not sure which is the best solution. I guess that whichever it is, we’d only be able to get it in a future version of react-native? Just for interest’s sake, if this projected updated it’s dependency from 0.61 (current) to 0.70 or 0.71, would this still be in a react-native patch release, or would we have to wait for 0.73?