-
Notifications
You must be signed in to change notification settings - Fork 61
[#424] Fix: app.rive.runtime.kotlin.core.errors.RiveException: Accessing disposed C++ object RiveArtboardRenderer. #429
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
base: master
Are you sure you want to change the base?
Changes from 2 commits
21616f8
3028f5c
d078c11
1afdd41
106a089
e716d17
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,5 @@ | ||
| package app.rive.runtime.kotlin.renderers | ||
|
|
||
| import androidx.annotation.VisibleForTesting | ||
| import androidx.annotation.WorkerThread | ||
| import app.rive.runtime.kotlin.controllers.RiveFileController | ||
| import app.rive.runtime.kotlin.core.Fit | ||
|
|
@@ -32,10 +31,7 @@ open class RiveArtboardRenderer( | |
| } | ||
|
|
||
| @WorkerThread | ||
| @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) | ||
| open fun resizeArtboard() { | ||
| if (!hasCppObject) return | ||
|
|
||
| private fun resizeArtboard() { | ||
| if (fit == Fit.LAYOUT) { | ||
| val newWidth = width / scaleFactor | ||
| val newHeight = height / scaleFactor | ||
|
|
@@ -51,16 +47,27 @@ open class RiveArtboardRenderer( | |
| // Be aware of thread safety! | ||
| @WorkerThread | ||
| override fun draw() { | ||
| if (controller.requireArtboardResize.getAndSet(false)) { | ||
| synchronized(controller.file?.lock ?: this) { resizeArtboard() } | ||
| } | ||
|
|
||
| // Deref and draw under frameLock | ||
| synchronized(frameLock) { | ||
| // Early out for deleted renderer or inactive controller. | ||
| // Note: controller.isActive can change at any time, but | ||
| // hasCppObject can only change while holding frameLock | ||
| if (!hasCppObject || !controller.isActive) return | ||
|
|
||
| controller.activeArtboard?.draw(cppPointer, fit, alignment, scaleFactor = scaleFactor) | ||
| // Protect both resize and draw operations with file.lock to prevent race conditions | ||
| // with file/artboard changes on the UI thread. This matches the locking strategy | ||
| // used in controller.advance() | ||
| synchronized(controller.file?.lock ?: this) { | ||
| if (controller.requireArtboardResize.getAndSet(false)) { | ||
| resizeArtboard() | ||
| } | ||
| controller.activeArtboard?.draw( | ||
| cppPointer, | ||
| fit, | ||
| alignment, | ||
| scaleFactor = scaleFactor | ||
| ) | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -92,7 +99,10 @@ open class RiveArtboardRenderer( | |
| } | ||
|
|
||
| override fun disposeDependencies() { | ||
| // Lock to make sure things are disposed in an orderly manner. | ||
| synchronized(controller.file?.lock ?: this) { super.disposeDependencies() } | ||
| // Lock to ensure dependencies are disposed in an orderly manner and to coordinate | ||
| // with any ongoing file/artboard operations that might be using these dependencies. | ||
| synchronized(controller.file?.lock ?: this) { | ||
| super.disposeDependencies() | ||
| } | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I just realized this could cause a deadlock with the above code. I am not even fully convinced that we really do need a File Lock on this, but if we do keep it, the order of lock obtainment needs to match the order in draw, so Frame Lock then File Lock.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I now have removed it. |
||
| } | ||
| } | ||
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 was not protected from race conditions because it didn't have the frameLock.