-
Notifications
You must be signed in to change notification settings - Fork 148
Mac RCTDisplayLink fix plus bonus deprecated API cleanup #854
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
Conversation
Real-world data suggests crashes with this stack: CVDisplayLink::start() -[RCTDisplayLink updateJSDisplayLinkState] (RCTDisplayLink.m:157) -[RCTDisplayLink registerModuleForFrameUpdates:withModuleData:]_block_invoke (RCTDisplayLink.m:67) -[RCTTiming timerDidFire] (RCTTiming.mm:324) -[_RCTTimingProxy timerDidFire] (RCTTiming.mm:93) Some symbols are missing in this stack, presumably due to compiler optimizations. -updateJSDisplayLinkState is calling CVDisplayLinkStart as a result of a call to "_jsDisplayLink.paused = NO". -registerModuleForFrameUpdates block is presumably getting called via pauseCallback, likely via [RCTTiming startTimers], presumably owned by RCTCxxBridge. The most likely immediate explanation for the crash is that we are calling CVDisplayLinkStart with a zombie _displayLink pointer. However there is a lot of indirection here as well as thread-hopping, and unfortunately no clearly incorrect code that would explain such a zombie pointer. Some defensive changes: -explicitly remove the association to pauseCallback when underlying display link object is invalidated. -remove a prior attempt at additional check in updateJSDisplayLinkState itself as it is not relevant. -make sure we explicitly set _displayLink to NULL when we release it, such that there is one less failure point.
|
this is great! @HeyImChris this change should really be in RNCore |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a great candidate to make the fix in FB's repo and we really don't want to introduce diffs if we can avoid it.
I think it's great to 1) keep this fix here 2) apply this fix to the 0.63-stable branch (what devmain uses) 3) apply this fix upstream to fb's fork 4) remove our macOS TODO tags since we'd be the same again.
I can help with any of these steps, but that'd probably be the most correct way to approach an awesome preventative fix like this!
Defensive changes to Mac RCTDisplayLink Real-world data suggests crashes with this stack: CVDisplayLink::start() -[RCTDisplayLink updateJSDisplayLinkState] (RCTDisplayLink.m:157) -[RCTDisplayLink registerModuleForFrameUpdates:withModuleData:]_block_invoke (RCTDisplayLink.m:67) -[RCTTiming timerDidFire] (RCTTiming.mm:324) -[_RCTTimingProxy timerDidFire] (RCTTiming.mm:93) Some symbols are missing in this stack, presumably due to compiler optimizations. -updateJSDisplayLinkState is calling CVDisplayLinkStart as a result of a call to "_jsDisplayLink.paused = NO". -registerModuleForFrameUpdates block is presumably getting called via pauseCallback, likely via [RCTTiming startTimers], presumably owned by RCTCxxBridge. The most likely immediate explanation for the crash is that we are calling CVDisplayLinkStart with a zombie _displayLink pointer. However there is a lot of indirection here as well as thread-hopping, and unfortunately no clearly incorrect code that would explain such a zombie pointer. Some defensive changes: -explicitly remove the association to pauseCallback when underlying display link object is invalidated. -remove a prior attempt at additional check in updateJSDisplayLinkState itself as it is not relevant. -make sure we explicitly set _displayLink to NULL when we release it, such that there is one less failure point.
* Mac RCTDisplayLink fix plus bonus deprecated API cleanup (#854) Defensive changes to Mac RCTDisplayLink Real-world data suggests crashes with this stack: CVDisplayLink::start() -[RCTDisplayLink updateJSDisplayLinkState] (RCTDisplayLink.m:157) -[RCTDisplayLink registerModuleForFrameUpdates:withModuleData:]_block_invoke (RCTDisplayLink.m:67) -[RCTTiming timerDidFire] (RCTTiming.mm:324) -[_RCTTimingProxy timerDidFire] (RCTTiming.mm:93) Some symbols are missing in this stack, presumably due to compiler optimizations. -updateJSDisplayLinkState is calling CVDisplayLinkStart as a result of a call to "_jsDisplayLink.paused = NO". -registerModuleForFrameUpdates block is presumably getting called via pauseCallback, likely via [RCTTiming startTimers], presumably owned by RCTCxxBridge. The most likely immediate explanation for the crash is that we are calling CVDisplayLinkStart with a zombie _displayLink pointer. However there is a lot of indirection here as well as thread-hopping, and unfortunately no clearly incorrect code that would explain such a zombie pointer. Some defensive changes: -explicitly remove the association to pauseCallback when underlying display link object is invalidated. -remove a prior attempt at additional check in updateJSDisplayLinkState itself as it is not relevant. -make sure we explicitly set _displayLink to NULL when we release it, such that there is one less failure point. * podfile update Co-authored-by: Nick Trescases <[email protected]>
Defensive changes to Mac RCTDisplayLink Real-world data suggests crashes with this stack: CVDisplayLink::start() -[RCTDisplayLink updateJSDisplayLinkState] (RCTDisplayLink.m:157) -[RCTDisplayLink registerModuleForFrameUpdates:withModuleData:]_block_invoke (RCTDisplayLink.m:67) -[RCTTiming timerDidFire] (RCTTiming.mm:324) -[_RCTTimingProxy timerDidFire] (RCTTiming.mm:93) Some symbols are missing in this stack, presumably due to compiler optimizations. -updateJSDisplayLinkState is calling CVDisplayLinkStart as a result of a call to "_jsDisplayLink.paused = NO". -registerModuleForFrameUpdates block is presumably getting called via pauseCallback, likely via [RCTTiming startTimers], presumably owned by RCTCxxBridge. The most likely immediate explanation for the crash is that we are calling CVDisplayLinkStart with a zombie _displayLink pointer. However there is a lot of indirection here as well as thread-hopping, and unfortunately no clearly incorrect code that would explain such a zombie pointer. Some defensive changes: -explicitly remove the association to pauseCallback when underlying display link object is invalidated. -remove a prior attempt at additional check in updateJSDisplayLinkState itself as it is not relevant. -make sure we explicitly set _displayLink to NULL when we release it, such that there is one less failure point.
Summary
First, misc straightforward deprecated API updates.
Second, defensive changes to potentially address RCTDisplayLink crash.
Real-world data suggests crashes with this stack:
CVDisplayLink::start()
-[RCTDisplayLink updateJSDisplayLinkState] (RCTDisplayLink.m:157)
-[RCTDisplayLink registerModuleForFrameUpdates:withModuleData:]_block_invoke (RCTDisplayLink.m:67)
-[RCTTiming timerDidFire] (RCTTiming.mm:324)
-[_RCTTimingProxy timerDidFire] (RCTTiming.mm:93)
Some symbols are missing in this stack, presumably due to compiler optimizations.
-updateJSDisplayLinkState is calling CVDisplayLinkStart as a result of a
call to "_jsDisplayLink.paused = NO".
-registerModuleForFrameUpdates block is presumably getting called via pauseCallback,
likely via [RCTTiming startTimers], presumably owned by RCTCxxBridge.
The most likely immediate explanation for the crash is that we are calling
CVDisplayLinkStart with a zombie _displayLink pointer.
However there is a lot of indirection here as well as thread-hopping, and
unfortunately no clearly incorrect code that would explain such a zombie pointer.
Some defensive changes:
-explicitly remove the association to pauseCallback when underlying display link object is invalidated.
-remove a prior attempt at additional check in updateJSDisplayLinkState itself as it is not relevant.
-make sure we explicitly set _displayLink to NULL when we release it, such that there is one less failure point.
Test Plan
N/A