From 0ddaddce2d4a7a61f3bf5adf9fb3d2a7a51e28e1 Mon Sep 17 00:00:00 2001 From: sunxiaodong Date: Mon, 21 Nov 2022 16:13:12 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0nativeDumpTrace?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../xcrash_lib/src/main/cpp/xcrash/xc_jni.c | 14 ++++++++ .../xcrash_lib/src/main/cpp/xcrash/xc_trace.c | 22 ++++++++++--- .../xcrash_lib/src/main/cpp/xcrash/xc_trace.h | 1 + .../main/java/xcrash/DumpTraceManager.java | 33 +++++++++++++++++++ .../src/main/java/xcrash/NativeHandler.java | 24 +++++++++++--- .../src/main/java/xcrash/XCrash.java | 10 +++++- 6 files changed, 94 insertions(+), 10 deletions(-) create mode 100644 third-party-libs/xcrash_lib/src/main/java/xcrash/DumpTraceManager.java diff --git a/third-party-libs/xcrash_lib/src/main/cpp/xcrash/xc_jni.c b/third-party-libs/xcrash_lib/src/main/cpp/xcrash/xc_jni.c index 697b80caa..db77eb795 100644 --- a/third-party-libs/xcrash_lib/src/main/cpp/xcrash/xc_jni.c +++ b/third-party-libs/xcrash_lib/src/main/cpp/xcrash/xc_jni.c @@ -229,6 +229,13 @@ static void xc_jni_test_crash(JNIEnv *env, jobject thiz, jint run_in_new_thread) xc_test_crash(run_in_new_thread); } +static void xc_jni_dump_trace(JNIEnv *env, jobject thiz) { + (void)env; + (void)thiz; + + xc_trace_handler_dump_trace(); +} + static JNINativeMethod xc_jni_methods[] = { { "nativeInit", @@ -281,6 +288,13 @@ static JNINativeMethod xc_jni_methods[] = { ")" "V", (void *)xc_jni_test_crash + }, + { + "nativeDumpTrace", + "(" + ")" + "V", + (void *)xc_jni_dump_trace } }; diff --git a/third-party-libs/xcrash_lib/src/main/cpp/xcrash/xc_trace.c b/third-party-libs/xcrash_lib/src/main/cpp/xcrash/xc_trace.c index 6a88003af..631c835bb 100644 --- a/third-party-libs/xcrash_lib/src/main/cpp/xcrash/xc_trace.c +++ b/third-party-libs/xcrash_lib/src/main/cpp/xcrash/xc_trace.c @@ -52,9 +52,11 @@ #define XC_TRACE_FAST_CALLBACK_METHOD_NAME "traceCallbackBeforeDump" #define XC_TRACE_FAST_CALLBACK_METHOD_SIGNATURE "()V" +#define XC_TRACE_CALLBACK_DUMP_FROM_SIGQUIT (1) +#define XC_TRACE_CALLBACK_DUMP_FROM_DUMP_TRACE (2) #define XC_TRACE_CALLBACK_METHOD_NAME "traceCallback" -#define XC_TRACE_CALLBACK_METHOD_SIGNATURE "(Ljava/lang/String;Ljava/lang/String;)V" +#define XC_TRACE_CALLBACK_METHOD_SIGNATURE "(Ljava/lang/String;Ljava/lang/String;J)V" #define XC_TRACE_SIGNAL_CATCHER_TID_UNLOAD (-2) #define XC_TRACE_SIGNAL_CATCHER_TID_UNKNOWN (-1) @@ -335,6 +337,7 @@ static void *xc_trace_dumper(void *arg) //write header info if(0 != xc_trace_write_header(fd, trace_time)) goto end; + if(0 != xcc_util_write_format(fd, "Dump From: '%s'\n\n", ((data == XC_TRACE_CALLBACK_DUMP_FROM_SIGQUIT) ? "SIGQUIT": "DUMP_TRACE"))) goto end; //write trace info from ART runtime if(0 != xcc_util_write_format(fd, XCC_UTIL_THREAD_SEP"Cmd line: %s\n", xc_common_process_name)) goto end; @@ -388,14 +391,13 @@ static void *xc_trace_dumper(void *arg) xc_common_close_trace_log(fd); //rethrow SIGQUIT to ART Signal Catcher - if(xc_trace_rethrow && (XC_TRACE_DUMP_ART_CRASH != xc_trace_dump_status)) xc_trace_send_sigquit(); - xc_trace_dump_status = XC_TRACE_DUMP_END; + if(data == XC_TRACE_CALLBACK_DUMP_FROM_SIGQUIT && xc_trace_rethrow) xc_trace_send_sigquit(); //JNI callback //Do we need to implement an emergency buffer for disk exhausted? if(NULL == xc_trace_cb_method) continue; if(NULL == (j_pathname = (*env)->NewStringUTF(env, pathname))) continue; - (*env)->CallStaticVoidMethod(env, xc_common_cb_class, xc_trace_cb_method, j_pathname, NULL); + (*env)->CallStaticVoidMethod(env, xc_common_cb_class, xc_trace_cb_method, j_pathname, NULL, data); XC_JNI_IGNORE_PENDING_EXCEPTION(); (*env)->DeleteLocalRef(env, j_pathname); } @@ -418,11 +420,21 @@ static void xc_trace_handler(int sig, siginfo_t *si, void *uc) if(xc_trace_notifier >= 0) { - data = 1; + data = XC_TRACE_CALLBACK_DUMP_FROM_SIGQUIT; XCC_UTIL_TEMP_FAILURE_RETRY(write(xc_trace_notifier, &data, sizeof(data))); } } +//notify fd from java +void xc_trace_handler_dump_trace(void) { + uint64_t data; + if (xc_trace_notifier >= 0) + { + data = XC_TRACE_CALLBACK_DUMP_FROM_DUMP_TRACE; + XCC_UTIL_TEMP_FAILURE_RETRY(write(xc_trace_notifier, &data, sizeof(data))); + } +} + static void xc_trace_init_callback(JNIEnv *env) { if(NULL == xc_common_cb_class) return; diff --git a/third-party-libs/xcrash_lib/src/main/cpp/xcrash/xc_trace.h b/third-party-libs/xcrash_lib/src/main/cpp/xcrash/xc_trace.h index a0ec2fd7d..0a732c3eb 100644 --- a/third-party-libs/xcrash_lib/src/main/cpp/xcrash/xc_trace.h +++ b/third-party-libs/xcrash_lib/src/main/cpp/xcrash/xc_trace.h @@ -51,6 +51,7 @@ int xc_trace_init(JNIEnv *env, int dump_fds, int dump_network_info); +void xc_trace_handler_dump_trace(void); #ifdef __cplusplus } #endif diff --git a/third-party-libs/xcrash_lib/src/main/java/xcrash/DumpTraceManager.java b/third-party-libs/xcrash_lib/src/main/java/xcrash/DumpTraceManager.java new file mode 100644 index 000000000..97c0050af --- /dev/null +++ b/third-party-libs/xcrash_lib/src/main/java/xcrash/DumpTraceManager.java @@ -0,0 +1,33 @@ +package xcrash; + +import java.util.Map; + +public class DumpTraceManager { + + public interface OnDumpTraceCallback{ + void OnDumpTrace(String trace); + } + + public static void dumpTrace(final OnDumpTraceCallback callback) { + ICrashCallback iCallback = new ICrashCallback() { + @Override + public void onCrash(String logPath, String emergency) throws Exception { + XCrash.getLogger().i(Util.TAG, "xCrash receive dumpCallback callback, path: " + logPath); + + Map map = TombstoneParser.parse(logPath, emergency); + + String trace = map.get(TombstoneParser.keyOtherThreads); + + TombstoneManager.deleteTombstone(logPath); + + callback.OnDumpTrace(trace); + + } + }; + + //需要5.0以上而且打开anrenable + if (!XCrash.dumpTrace(iCallback)) { + callback.OnDumpTrace(""); + } + } +} diff --git a/third-party-libs/xcrash_lib/src/main/java/xcrash/NativeHandler.java b/third-party-libs/xcrash_lib/src/main/java/xcrash/NativeHandler.java index f41c68afe..6aca6a2e3 100644 --- a/third-party-libs/xcrash_lib/src/main/java/xcrash/NativeHandler.java +++ b/third-party-libs/xcrash_lib/src/main/java/xcrash/NativeHandler.java @@ -37,6 +37,8 @@ class NativeHandler { private static final String TAG = "xcrash"; private static final NativeHandler instance = new NativeHandler(); private long anrTimeoutMs = 25 * 1000; + private static final int DUMP_TRACE_FROM_SIGQUIT = 1; + private static final int DUMP_TRACE_FROM_DUMP_TRACE = 2; private Context ctx; private boolean crashRethrow; @@ -45,6 +47,7 @@ class NativeHandler { private boolean anrCheckProcessState; private ICrashCallback anrCallback; private ICrashCallback anrFastCallback; + private ICrashCallback dumpTraceCallBack; private boolean initNativeLibOk = false; @@ -154,6 +157,15 @@ class NativeHandler { } } + boolean dumpTrace(ICrashCallback dumpCallBack) { + if (initNativeLibOk && anrEnable) { + dumpTraceCallBack = dumpCallBack; + NativeHandler.nativeDumpTrace(); + return true; + } + return false; + } + void notifyJavaCrashed() { if (initNativeLibOk && anrEnable) { NativeHandler.nativeNotifyJavaCrashed(); @@ -235,7 +247,7 @@ class NativeHandler { // do NOT obfuscate this method @SuppressWarnings("unused") - private static void traceCallback(String logPath, String emergency) { + private static void traceCallback(String logPath, String emergency, long dumpTrace) { Log.i(TAG, "trace slow callback time: " + System.currentTimeMillis()); if (TextUtils.isEmpty(logPath)) { @@ -248,8 +260,8 @@ class NativeHandler { //append background / foreground TombstoneManager.appendSection(logPath, "foreground", ActivityMonitor.getInstance().isApplicationForeground() ? "yes" : "no"); - //check process ANR state - if (NativeHandler.getInstance().anrCheckProcessState) { + //check process ANR state,dumptrace不需要进行process + if (dumpTrace != DUMP_TRACE_FROM_DUMP_TRACE && NativeHandler.getInstance().anrCheckProcessState) { if (!Util.checkProcessAnrState(NativeHandler.getInstance().ctx, NativeHandler.getInstance().anrTimeoutMs)) { FileManager.getInstance().recycleLogFile(new File(logPath)); return; //not an ANR @@ -270,7 +282,9 @@ class NativeHandler { return; } - ICrashCallback callback = NativeHandler.getInstance().anrCallback; + ICrashCallback callback = (dumpTrace == DUMP_TRACE_FROM_SIGQUIT) + ? NativeHandler.getInstance().anrCallback + : NativeHandler.getInstance().dumpTraceCallBack; if (callback != null) { try { callback.onCrash(anrLogPath, emergency); @@ -315,4 +329,6 @@ class NativeHandler { private static native void nativeNotifyJavaCrashed(); private static native void nativeTestCrash(int runInNewThread); + + private static native void nativeDumpTrace(); } diff --git a/third-party-libs/xcrash_lib/src/main/java/xcrash/XCrash.java b/third-party-libs/xcrash_lib/src/main/java/xcrash/XCrash.java index 73821b08f..250b849b2 100644 --- a/third-party-libs/xcrash_lib/src/main/java/xcrash/XCrash.java +++ b/third-party-libs/xcrash_lib/src/main/java/xcrash/XCrash.java @@ -33,13 +33,17 @@ import android.text.TextUtils; @SuppressWarnings("unused") public final class XCrash { - private static boolean initialized = false; + public static boolean initialized = false; private static String appId = null; private static String appVersion = null; private static String logDir = null; private static ILogger logger = new DefaultLogger(); public static String nativeLibDir = null; + public static boolean initialized(){ + return initialized; + } + private XCrash() { } @@ -923,4 +927,8 @@ public final class XCrash { public static void testNativeCrash(boolean runInNewThread) { NativeHandler.getInstance().testNativeCrash(runInNewThread); } + + public static boolean dumpTrace(ICrashCallback dumpCallBack) { + return NativeHandler.getInstance().dumpTrace(dumpCallBack); + } } -- 2.37.1 (Apple Git-137.1)