diff --git a/packages/skia/cpp/rnskia/RNSkPictureView.h b/packages/skia/cpp/rnskia/RNSkPictureView.h index 5535f8fb30..efca635877 100644 --- a/packages/skia/cpp/rnskia/RNSkPictureView.h +++ b/packages/skia/cpp/rnskia/RNSkPictureView.h @@ -52,17 +52,30 @@ class RNSkPictureRenderer } void setPicture(sk_sp picture) { - _picture = picture; + { + std::lock_guard lock(_pictureMutex); + _picture = std::move(picture); + } _requestRedraw(); } - sk_sp getPicture() const { return _picture; } + sk_sp getPicture() const { + std::lock_guard lock(_pictureMutex); + return _picture; + } private: bool performDraw(std::shared_ptr canvasProvider) { - // Capture picture pointer to ensure thread safety - _picture can be - // modified from the JS thread while we're drawing on the render thread - sk_sp picture = _picture; + // Copy under the lock: _picture can be replaced from the JS thread while + // the render thread draws, and copying an sk_sp is not atomic. Without + // the lock, this copy can ref a picture whose count the replacement on + // the other thread has already taken to zero, and drawing it fails in + // __cxa_pure_virtual. + sk_sp picture; + { + std::lock_guard lock(_pictureMutex); + picture = _picture; + } auto pd = _platformContext->getPixelDensity(); return canvasProvider->renderToCanvas([=](SkCanvas *canvas) { canvas->clear(SK_ColorTRANSPARENT); @@ -77,6 +90,7 @@ class RNSkPictureRenderer std::shared_ptr _platformContext; sk_sp _picture; + mutable std::mutex _pictureMutex; }; class RNSkPictureView : public RNSkView {