This is an automated email from the ASF dual-hosted git repository. luckychen pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-weex.git
The following commit(s) were added to refs/heads/master by this push: new 5e8d9ac [Android] Fix Crash in NotifyLayout (#2902) 5e8d9ac is described below commit 5e8d9ac935d6fbadd2469d83540426cc30b4e676 Author: YorkShen <shenyua...@gmail.com> AuthorDate: Mon Sep 16 16:20:43 2019 +0800 [Android] Fix Crash in NotifyLayout (#2902) There is a concurrent read/write operation to `RenderManager::pages_` during `CoreSideInPlatform::NotifyLayout`where MainThread is reading `RenderManager::pages_` while other thread may be writing to it. ``` std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >::__is_long() const at string:1266 (inlined by) std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >::size() const at string:905 (inlined by) std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >::compare(std::__ndk1::basic_string_view<char, std::__ndk1::char_traits<char> >) const at string:3455 (inlined by) std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >::compare(std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > const&) const at string:3473 (inlined by) bool std::__ndk1::operator< <char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >(std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > const&, std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > const&) at string:3693 (inlined by) std::__ndk1::less<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > >::operator()(std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > const&, std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > const&) const at __functional_base:55 (inlined by) std::__ndk1::__map_value_compare<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >, std::__ndk1::__value_type<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >, WeexCore::RenderPageBase*>, std::__ndk1::less<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > >, true>::operator()(std::__ndk1::__value_type<std::__ndk1::basic_string<char, std: [...] (inlined by) std::__ndk1::__tree_iterator<std::__ndk1::__value_type<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >, WeexCore::RenderPageBase*>, std::__ndk1::__tree_node<std::__ndk1::__value_type<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >, WeexCore::RenderPageBase*>, void*>*, int> std::__ndk1::__tree<std::__ndk1::__value_type<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char [...] std::__ndk1::__tree_iterator<std::__ndk1::__value_type<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >, WeexCore::RenderPageBase*>, std::__ndk1::__tree_node<std::__ndk1::__value_type<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >, WeexCore::RenderPageBase*>, void*>*, int> std::__ndk1::__tree<std::__ndk1::__value_type<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1 [...] std::__ndk1::map<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >, WeexCore::RenderPageBase*, std::__ndk1::less<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > >, std::__ndk1::allocator<std::__ndk1::pair<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > const, WeexCore::RenderPageBase*> > >::find(std::__ndk1::basic_string<char, std::__ndk1::char_tra [...] (inlined by) WeexCore::RenderManager::GetPage(std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > const&) at render_manager.cpp:472 WeexCore::CoreSideInPlatform::NotifyLayout(std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > const&) at core_side_in_platform.cpp:223 ``` --- .../java/com/taobao/weex/WeexFrameRateControl.java | 52 ++++++++++++---------- .../com/taobao/weex/bridge/WXBridgeManager.java | 6 +-- 2 files changed, 32 insertions(+), 26 deletions(-) diff --git a/android/sdk/src/main/java/com/taobao/weex/WeexFrameRateControl.java b/android/sdk/src/main/java/com/taobao/weex/WeexFrameRateControl.java index eef4d5c..14817fd 100644 --- a/android/sdk/src/main/java/com/taobao/weex/WeexFrameRateControl.java +++ b/android/sdk/src/main/java/com/taobao/weex/WeexFrameRateControl.java @@ -26,14 +26,15 @@ import android.annotation.SuppressLint; import android.os.Build; import android.util.Log; import android.view.Choreographer; +import com.taobao.weex.bridge.WXBridgeManager; import com.taobao.weex.common.WXErrorCode; import java.lang.ref.WeakReference; public class WeexFrameRateControl { private static final long VSYNC_FRAME = 1000 / 60; private WeakReference<VSyncListener> mListener; - private final Choreographer mChoreographer; - private final Choreographer.FrameCallback mVSyncFrameCallback; + private Choreographer mChoreographer; + private Choreographer.FrameCallback mVSyncFrameCallback; private final Runnable runnable; public interface VSyncListener { @@ -43,27 +44,32 @@ public class WeexFrameRateControl { public WeexFrameRateControl(VSyncListener listener) { mListener = new WeakReference<>(listener); if (Build.VERSION.SDK_INT > Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) { - mChoreographer = Choreographer.getInstance(); - mVSyncFrameCallback = new Choreographer.FrameCallback() { - @SuppressLint("NewApi") - @Override - public void doFrame(long frameTimeNanos) { - VSyncListener vSyncListener; - if (mListener != null && (vSyncListener=mListener.get()) != null) { - try { - vSyncListener.OnVSync(); - mChoreographer.postFrameCallback(mVSyncFrameCallback); - }catch (UnsatisfiedLinkError e){ - if(vSyncListener instanceof WXSDKInstance){ - ((WXSDKInstance) vSyncListener).onRenderError( - WXErrorCode.WX_DEGRAD_ERR_INSTANCE_CREATE_FAILED.getErrorCode(), - Log.getStackTraceString(e)); - } - } - } - } - }; - runnable = null; + WXBridgeManager.getInstance().post(new Runnable() { + @Override + public void run() { + mChoreographer = Choreographer.getInstance(); + mVSyncFrameCallback = new Choreographer.FrameCallback() { + @SuppressLint("NewApi") + @Override + public void doFrame(long frameTimeNanos) { + VSyncListener vSyncListener; + if (mListener != null && (vSyncListener=mListener.get()) != null) { + try { + vSyncListener.OnVSync(); + mChoreographer.postFrameCallback(mVSyncFrameCallback); + }catch (UnsatisfiedLinkError e){ + if(vSyncListener instanceof WXSDKInstance){ + ((WXSDKInstance) vSyncListener).onRenderError( + WXErrorCode.WX_DEGRAD_ERR_INSTANCE_CREATE_FAILED.getErrorCode(), + Log.getStackTraceString(e)); + } + } + } + } + }; + } + }); + runnable = null; } else { // For API 15 or lower runnable = new Runnable() { diff --git a/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridgeManager.java b/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridgeManager.java index 8c31da1..ccbb45f 100755 --- a/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridgeManager.java +++ b/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridgeManager.java @@ -31,7 +31,7 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.RestrictTo; import android.support.annotation.RestrictTo.Scope; -import android.support.annotation.UiThread; +import android.support.annotation.WorkerThread; import android.support.v4.util.ArrayMap; import android.text.TextUtils; import android.util.Log; @@ -3449,7 +3449,7 @@ public class WXBridgeManager implements Callback, BactchExecutor { * @param instanceId * @return */ - @UiThread + @WorkerThread public boolean notifyLayout(String instanceId) { if (isSkipFrameworkInit(instanceId) || isJSFrameworkInit()) { return mWXBridge.notifyLayout(instanceId); @@ -3457,7 +3457,7 @@ public class WXBridgeManager implements Callback, BactchExecutor { return false; } - @UiThread + @WorkerThread public void forceLayout(String instanceId) { if (isSkipFrameworkInit(instanceId) || isJSFrameworkInit()) { mWXBridge.forceLayout(instanceId);