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 a774e888b5..23d40896d9 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 @@ private void checkWhiteScreen(){ Map 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 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 d363651144..145730c043 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 int callReportCrashReloadPage(String instanceId, String crashFile) { url = instance.getBundleUrl(); instance.setHasException(true); } + Map 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 int callReportCrashReloadPage(String instanceId, String crashFile) { 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 boolean shouldReloadCurrentInstance(String aUrl) { 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 extInfo) { // statistic weex core process crash Date date = new Date(); DateFormat format = new SimpleDateFormat("yyyyMMddHHmmss", Locale.US); @@ -1005,7 +1009,7 @@ public void run() { // } 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 @@ private void invokeRefreshInstance(String instanceId, WXRefreshData refreshData) } public void commitJscCrashAlarmMonitor(final String type, final WXErrorCode errorCode, String errMsg, - String instanceId, String url) { + String instanceId, String url,Map extInfo) { if (TextUtils.isEmpty(type) || errorCode == null) { return; } @@ -1483,6 +1487,9 @@ public void commitJscCrashAlarmMonitor(final String type, final WXErrorCode erro String exception = "weex core process crash and restart exception"; Map extParams = new HashMap(); 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 @@ private void onJsFrameWorkInitSuccees() { } 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 700d419ea1..a95e957e55 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 mJscCrashHistory; private RecordList mJscReloadHistory; private RecordList mJsThradWatchHistory; + private RecordList mIPCExceptionHistory; private static class SingleTonHolder { private static final WXStateRecord S_INSTANCE = new WXStateRecord(); @@ -60,6 +61,7 @@ private WXStateRecord() { mJscCrashHistory = new RecordList<>(10); mJscReloadHistory = new RecordList<>(10); mJsThradWatchHistory = new RecordList<>(20); + mIPCExceptionHistory = new RecordList<>(20); } /** @@ -77,6 +79,11 @@ public void recordAction(String instanceId, String action) { 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 Map getStateInfo() { 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 RecordList(int maxSize) { 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{ @@ -174,7 +171,7 @@ public Info(long time, String instance, String msg) { @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 2560777009..d8bc7a9fc9 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.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 @@ private static void log(String tag, String msg, LogLevel level){ 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 9958f21a21..36e853cbe3 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 result = sender_->send(buffer.get()); return result->get(); } 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 result = sender_->send(buffer.get()); return result->get(); } 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 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(); } 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 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(); } 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 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(); } 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 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 ret; try { if(sender_ == nullptr) { - LOGE("ExecJSWithResult sender is null"); + LOGE("IPCException ExecJSWithResult sender is null"); return; } std::unique_ptr serializer(createIPCSerializer()); @@ -421,7 +421,7 @@ void ScriptSideInMultiProcess::ExecJSWithCallback( std::unique_ptr 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(); } 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 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(); } 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 buffer = serializer->finish(); std::unique_ptr 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 buffer = serializer->finish(); std::unique_ptr 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 buffer = serializer->finish(); std::unique_ptr 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 ffc3d45912..11bd292b89 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 fd9b72dbe7..3699192d34 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;