This is an automated email from the ASF dual-hosted git repository. dongyayun 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 a994ce9 [Android] record ipc exception history and weexCoreThread stackTrace when white screen or js process died/reload (#2826) a994ce9 is described below commit a994ce97e72535032dccf9007471f7f890765356 Author: chen <lucky-c...@users.noreply.github.com> AuthorDate: Wed Aug 14 18:10:50 2019 +0800 [Android] record ipc exception history and weexCoreThread stackTrace when white screen or js process died/reload (#2826) --- .../main/java/com/taobao/weex/WXSDKInstance.java | 1 + .../com/taobao/weex/bridge/WXBridgeManager.java | 39 ++++++++++++++++++---- .../com/taobao/weex/performance/WXStateRecord.java | 21 +++++------- .../java/com/taobao/weex/utils/WXLogUtils.java | 4 +++ .../bridge/script/script_side_in_multi_process.cpp | 36 ++++++++++---------- .../android/multiprocess/weex_js_connection.cpp | 2 +- .../Source/third_party/IPC/IPCFutexPageQueue.cpp | 1 + 7 files changed, 67 insertions(+), 37 deletions(-) diff --git a/android/sdk/src/main/java/com/taobao/weex/WXSDKInstance.java b/android/sdk/src/main/java/com/taobao/weex/WXSDKInstance.java index a774e88..23d4089 100644 --- a/android/sdk/src/main/java/com/taobao/weex/WXSDKInstance.java +++ b/android/sdk/src/main/java/com/taobao/weex/WXSDKInstance.java @@ -944,6 +944,7 @@ public class WXSDKInstance implements IWXActivityStateListener,View.OnLayoutChan Map<String,String> args = new HashMap<>(1); String vieTreeMsg = WhiteScreenUtils.takeViewTreeSnapShot(this); args.put("viewTree",null == vieTreeMsg?"null viewTreeMsg":vieTreeMsg); + args.put("weexCoreThreadStackTrace",WXBridgeManager.getInstance().getWeexCoreThreadStackTrace()); for (Map.Entry<String,String> entry: WXStateRecord.getInstance().getStateInfo().entrySet()){ args.put(entry.getKey(),entry.getValue()); 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 d363651..145730c 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 @@ -884,6 +884,10 @@ public class WXBridgeManager implements Callback, BactchExecutor { url = instance.getBundleUrl(); instance.setHasException(true); } + Map<String,String> extInfo = new HashMap<>(2); + extInfo.put("weexCoreThreadStackTrace:",WXBridgeManager.getInstance().getWeexCoreThreadStackTrace()); + extInfo.put("wxStateInfo",WXStateRecord.getInstance().getStateInfo().toString()); + if(!isCrashFileEmpty) { try { if (WXEnvironment.getApplication() != null) { @@ -894,15 +898,15 @@ public class WXBridgeManager implements Callback, BactchExecutor { WXLogUtils.e(WXLogUtils.getStackTrace(e)); } WXStateRecord.getInstance().onJSCCrash(); - callReportCrash(crashFile, instanceId, url); + callReportCrash(crashFile, instanceId, url,extInfo); } else { WXStateRecord.getInstance().onJSEngineReload(); - commitJscCrashAlarmMonitor(IWXUserTrackAdapter.JS_BRIDGE, WXErrorCode.WX_ERR_RELOAD_PAGE, "reboot jsc Engine", instanceId, url); + commitJscCrashAlarmMonitor(IWXUserTrackAdapter.JS_BRIDGE, WXErrorCode.WX_ERR_RELOAD_PAGE, "reboot jsc Engine", instanceId, url,extInfo); } if (reInitCount > CRASHREINIT) { WXExceptionUtils.commitCriticalExceptionRT("jsEngine", WXErrorCode.WX_ERR_RELOAD_PAGE_EXCEED_LIMIT, - "callReportCrashReloadPage","reInitCount:"+reInitCount,null); + "callReportCrashReloadPage","reInitCount:"+reInitCount,extInfo); return IWXBridge.INSTANCE_RENDERING_ERROR; } reInitCount++; @@ -974,7 +978,7 @@ public class WXBridgeManager implements Callback, BactchExecutor { return false; } - public void callReportCrash(String crashFile, final String instanceId, final String url) { + public void callReportCrash(String crashFile, final String instanceId, final String url,final Map<String,String> extInfo) { // statistic weex core process crash Date date = new Date(); DateFormat format = new SimpleDateFormat("yyyyMMddHHmmss", Locale.US); @@ -1005,7 +1009,7 @@ public class WXBridgeManager implements Callback, BactchExecutor { // } result.append(s + "\n"); } - commitJscCrashAlarmMonitor(IWXUserTrackAdapter.JS_BRIDGE, WXErrorCode.WX_ERR_JSC_CRASH, result.toString(), instanceId, url); + commitJscCrashAlarmMonitor(IWXUserTrackAdapter.JS_BRIDGE, WXErrorCode.WX_ERR_JSC_CRASH, result.toString(), instanceId, url,extInfo); br.close(); } catch (Exception e) { WXLogUtils.e(WXLogUtils.getStackTrace(e)); @@ -1473,7 +1477,7 @@ public class WXBridgeManager implements Callback, BactchExecutor { } public void commitJscCrashAlarmMonitor(final String type, final WXErrorCode errorCode, String errMsg, - String instanceId, String url) { + String instanceId, String url,Map<String, String> extInfo) { if (TextUtils.isEmpty(type) || errorCode == null) { return; } @@ -1483,6 +1487,9 @@ public class WXBridgeManager implements Callback, BactchExecutor { String exception = "weex core process crash and restart exception"; Map<String, String> extParams = new HashMap<String, String>(); extParams.put("jscCrashStack", errMsg); + if (null != extInfo){ + extParams.putAll(extInfo); + } IWXJSExceptionAdapter adapter = WXSDKManager.getInstance().getIWXJSExceptionAdapter(); if (adapter != null) { WXJSExceptionInfo jsException = new WXJSExceptionInfo(instanceId, url, errorCode, method, exception, extParams); @@ -3614,4 +3621,24 @@ public class WXBridgeManager implements Callback, BactchExecutor { } mWeexCoreEnvOptions.clear(); } + + public String getWeexCoreThreadStackTrace(){ + if (null == mJSThread){ + return "null == mJSThread"; + } + StringBuilder stringBuilder = new StringBuilder(); + + try { + stringBuilder.append(String.format("Thread Name: '%s'\n", mJSThread.getName())); + stringBuilder.append(String.format(Locale.ENGLISH,"\"%s\" prio=%d tid=%d %s\n", mJSThread.getName(), mJSThread.getPriority(), mJSThread.getId(), mJSThread.getState())); + + for (StackTraceElement e: mJSThread.getStackTrace()){ + stringBuilder.append(String.format("\tat %s\n", e.toString())); + } + } catch (Exception var8) { + Log.e("weex", "getJSThreadStackTrace error:", var8); + } + return stringBuilder.toString(); + } + } diff --git a/android/sdk/src/main/java/com/taobao/weex/performance/WXStateRecord.java b/android/sdk/src/main/java/com/taobao/weex/performance/WXStateRecord.java index 700d419..a95e957 100644 --- a/android/sdk/src/main/java/com/taobao/weex/performance/WXStateRecord.java +++ b/android/sdk/src/main/java/com/taobao/weex/performance/WXStateRecord.java @@ -44,6 +44,7 @@ public class WXStateRecord { private RecordList<Info> mJscCrashHistory; private RecordList<Info> mJscReloadHistory; private RecordList<Info> mJsThradWatchHistory; + private RecordList<Info> mIPCExceptionHistory; private static class SingleTonHolder { private static final WXStateRecord S_INSTANCE = new WXStateRecord(); @@ -60,6 +61,7 @@ public class WXStateRecord { mJscCrashHistory = new RecordList<>(10); mJscReloadHistory = new RecordList<>(10); mJsThradWatchHistory = new RecordList<>(20); + mIPCExceptionHistory = new RecordList<>(20); } /** @@ -77,6 +79,11 @@ public class WXStateRecord { recordCommon(mActionHistory,new Info(WXUtils.getFixUnixTime(), instanceId, action)); } + public void recordIPCException (String instanceId,String exception){ + String shortException = exception.length() > 200 ?exception.substring(0,200) : exception; + recordCommon(mIPCExceptionHistory,new Info(WXUtils.getFixUnixTime(), instanceId, shortException)); + } + /** * check onJSFMInit time,and we know when jsfm is init sucess in reloadJsEngine case */ @@ -134,6 +141,7 @@ public class WXStateRecord { reportTimeLineInfo.addAll(mJscCrashHistory); reportTimeLineInfo.addAll(mJscReloadHistory); reportTimeLineInfo.addAll(mJsThradWatchHistory); + reportTimeLineInfo.addAll(mIPCExceptionHistory); Collections.sort(reportTimeLineInfo); stateInfo.put("stateInfoList",reportTimeLineInfo.toString()); @@ -147,17 +155,6 @@ public class WXStateRecord { super(); this.maxSize = maxSize; } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - E e = this.poll(); - while (null != e){ - builder.append('[').append(e.toString()).append(']').append("->"); - e = this.poll(); - } - return builder.toString(); - } } private static class Info implements Comparable<Info>{ @@ -174,7 +171,7 @@ public class WXStateRecord { @Override public String toString() { return new StringBuilder() - .append(instanceId).append(',').append(time).append(',').append(msg) + .append('[').append(instanceId).append(',').append(time).append(',').append(msg).append("]->") .toString(); } diff --git a/android/sdk/src/main/java/com/taobao/weex/utils/WXLogUtils.java b/android/sdk/src/main/java/com/taobao/weex/utils/WXLogUtils.java index 2560777..d8bc7a9 100644 --- a/android/sdk/src/main/java/com/taobao/weex/utils/WXLogUtils.java +++ b/android/sdk/src/main/java/com/taobao/weex/utils/WXLogUtils.java @@ -26,6 +26,7 @@ import com.alibaba.fastjson.JSON; import com.taobao.weex.WXEnvironment; import com.taobao.weex.WXSDKInstance; import com.taobao.weex.WXSDKManager; +import com.taobao.weex.performance.WXStateRecord; import com.taobao.weex.utils.tools.LogDetail; import java.io.IOException; @@ -81,6 +82,9 @@ public class WXLogUtils { if(TextUtils.isEmpty(msg) || TextUtils.isEmpty(tag) || level == null || TextUtils.isEmpty(level.getName())){ return; } + if (level == LogLevel.ERROR && !TextUtils.isEmpty(msg) && msg.contains("IPCException")){ + WXStateRecord.getInstance().recordIPCException("ipc",msg); + } if(sLogWatcher !=null){ sLogWatcher.onLog(level.getName(), tag, msg); diff --git a/weex_core/Source/android/bridge/script/script_side_in_multi_process.cpp b/weex_core/Source/android/bridge/script/script_side_in_multi_process.cpp index 9958f21..36e853c 100644 --- a/weex_core/Source/android/bridge/script/script_side_in_multi_process.cpp +++ b/weex_core/Source/android/bridge/script/script_side_in_multi_process.cpp @@ -59,7 +59,7 @@ int ScriptSideInMultiProcess::InitFramework( return false; } } catch (IPCException &e) { - LOGE("%s", e.msg()); + LOGE("IPCException InitFramework %s", e.msg()); return false; } return true; @@ -88,7 +88,7 @@ int ScriptSideInMultiProcess::InitAppFramework( std::unique_ptr<IPCResult> result = sender_->send(buffer.get()); return result->get<jint>(); } catch (IPCException &e) { - LOGE("initAppFramework error %s", e.msg()); + LOGE("IPCException initAppFramework error %s", e.msg()); // report crash here WeexCoreManager::Instance() ->getPlatformBridge() @@ -115,7 +115,7 @@ int ScriptSideInMultiProcess::CreateAppContext(const char *instanceId, std::unique_ptr<IPCResult> result = sender_->send(buffer.get()); return result->get<jint>(); } catch (IPCException &e) { - LOGE("%s", e.msg()); + LOGE("IPCException CreateAppContext %s", e.msg()); // report crash here WeexCoreManager::Instance() ->getPlatformBridge() @@ -156,7 +156,7 @@ std::unique_ptr<WeexJSResult> ScriptSideInMultiProcess::ExecJSOnAppWithResult(co return ret; } catch (IPCException &e) { - LOGE("%s", e.msg()); + LOGE("IPCException ExecJSOnAppWithResult %s", e.msg()); // report crash here WeexCoreManager::Instance() ->getPlatformBridge() @@ -204,7 +204,7 @@ int ScriptSideInMultiProcess::CallJSOnAppContext( } return result->get<jint>(); } catch (IPCException &e) { - LOGE("%s", e.msg()); + LOGE("IPCException CallJSOnAppContext %s", e.msg()); // report crash here WeexCoreManager::Instance() ->getPlatformBridge() @@ -228,7 +228,7 @@ int ScriptSideInMultiProcess::DestroyAppContext(const char *instanceId) { std::unique_ptr<IPCResult> result = sender_->send(buffer.get()); return true; } catch (IPCException &e) { - LOGE("%s", e.msg()); + LOGE("IPCException DestroyAppContext %s", e.msg()); // report crash here WeexCoreManager::Instance() ->getPlatformBridge() @@ -255,7 +255,7 @@ int ScriptSideInMultiProcess::ExecJsService(const char *source) { } return result->get<jint>(); } catch (IPCException &e) { - LOGE("%s", e.msg()); + LOGE("IPCException ExecJsService error %s", e.msg()); return false; } } @@ -304,14 +304,14 @@ int ScriptSideInMultiProcess::ExecJS(const char *instanceId, std::unique_ptr<IPCResult> result = sender_->send(buffer.get()); if (result->getType() != IPCType::INT32) { - LOGE("execJS Unexpected result type"); + LOGE("IPCException execJS Unexpected result type"); return false; } return result->get<jint>(); } catch (IPCException &e) { - LOGE("%s", e.msg()); + LOGE("IPCException ExecJS %s", e.msg()); // report crash here WeexCoreManager::Instance() ->getPlatformBridge() @@ -380,7 +380,7 @@ std::unique_ptr<WeexJSResult> ScriptSideInMultiProcess::ExecJSWithResult( return ret; } catch (IPCException &e) { - LOGE("%s", e.msg()); + LOGE("IPCException ExecJSWithResult %s", e.msg()); // report crash here WeexCoreManager::Instance() ->getPlatformBridge() @@ -396,7 +396,7 @@ void ScriptSideInMultiProcess::ExecJSWithCallback( std::unique_ptr<WeexJSResult> ret; try { if(sender_ == nullptr) { - LOGE("ExecJSWithResult sender is null"); + LOGE("IPCException ExecJSWithResult sender is null"); return; } std::unique_ptr<IPCSerializer> serializer(createIPCSerializer()); @@ -421,7 +421,7 @@ void ScriptSideInMultiProcess::ExecJSWithCallback( std::unique_ptr<IPCResult> result = sender_->send(buffer.get()); } catch (IPCException &e) { - LOGE("%s", e.msg()); + LOGE("IPCException ExecJSWithCallback %s", e.msg()); // report crash here WeexCoreManager::Instance() ->getPlatformBridge() @@ -461,7 +461,7 @@ int ScriptSideInMultiProcess::CreateInstance( } return result->get<jint>(); } catch (IPCException &e) { - LOGE("%s %s","Create Instance is failed and Error msg is", e.msg()); + LOGE("IPCException %s %s","Create Instance is failed and Error msg is", e.msg()); // report crash here WeexCoreManager::Instance() ->getPlatformBridge() @@ -498,7 +498,7 @@ std::unique_ptr<WeexJSResult> ScriptSideInMultiProcess::ExecJSOnInstance(const c string[ret->length] = '\0'; return ret; } catch (IPCException &e) { - LOGE("%s", e.msg()); + LOGE("IPCException ExecJSOnInstance %s", e.msg()); // report crash here WeexCoreManager::Instance() ->getPlatformBridge() @@ -526,7 +526,7 @@ int ScriptSideInMultiProcess::DestroyInstance(const char *instanceId) { } return result->get<jint>(); } catch (IPCException &e) { - LOGE("%s", e.msg()); + LOGE("IPCException DestroyInstance %s", e.msg()); // report crash here WeexCoreManager::Instance() ->getPlatformBridge() @@ -548,7 +548,7 @@ int ScriptSideInMultiProcess::UpdateGlobalConfig(const char *config) { std::unique_ptr<IPCBuffer> buffer = serializer->finish(); std::unique_ptr<IPCResult> result = sender_->send(buffer.get()); } catch (IPCException &e) { - LOGE("%s", e.msg()); + LOGE("IPCException UpdateGlobalConfig %s", e.msg()); } return true; } @@ -569,7 +569,7 @@ int ScriptSideInMultiProcess::UpdateInitFrameworkParams(const std::string &key, std::unique_ptr<IPCBuffer> buffer = serializer->finish(); std::unique_ptr<IPCResult> result = sender_->send(buffer.get()); } catch (IPCException &e) { - LOGE("%s", e.msg()); + LOGE("IPCException UpdateInitFrameworkParams %s", e.msg()); } return true; @@ -588,7 +588,7 @@ void ScriptSideInMultiProcess::SetLogType(const int logLevel, const bool isPerf) std::unique_ptr<IPCBuffer> buffer = serializer->finish(); std::unique_ptr<IPCResult> result = sender_->send(buffer.get()); } catch (IPCException &e) { - LOGE("%s", e.msg()); + LOGE("IPCException SetLogType %s", e.msg()); } return; } diff --git a/weex_core/Source/android/multiprocess/weex_js_connection.cpp b/weex_core/Source/android/multiprocess/weex_js_connection.cpp index ffc3d45..11bd292 100644 --- a/weex_core/Source/android/multiprocess/weex_js_connection.cpp +++ b/weex_core/Source/android/multiprocess/weex_js_connection.cpp @@ -189,7 +189,7 @@ static void *newIPCServer(void *_td) { futexPageQueue->spinWaitPeer(); listener->listen(); } catch (IPCException &e) { - LOGE("server died"); + LOGE("IPCException server died %s",e.msg()); closeServerFd(td->ipcServerFd); base::android::DetachFromVM(); pthread_exit(NULL); diff --git a/weex_core/Source/third_party/IPC/IPCFutexPageQueue.cpp b/weex_core/Source/third_party/IPC/IPCFutexPageQueue.cpp index fd9b72d..3699192 100644 --- a/weex_core/Source/third_party/IPC/IPCFutexPageQueue.cpp +++ b/weex_core/Source/third_party/IPC/IPCFutexPageQueue.cpp @@ -112,6 +112,7 @@ void IPCFutexPageQueue::lock(size_t id, bool checkFinish) break; } struct timespec waitTime = { m_timeoutSec, 0 }; + IPC_LOGE("IPCException IPCFutexPageQueue:: start futex wait"); int futexReturn = __futex(pageStart + 1, FUTEX_WAIT, 0, &waitTime); if (futexReturn == -1) { int myerrno = errno;